Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pg_walviz

pg_walviz is a read-only PostgreSQL WAL segment visualizer. It maps the physical bytes in one or more segment files and presents WAL pages, records, continuations, alignment padding, block references, full-page images, and raw bytes in a local browser.

Current release: v0.1.0-beta.1.

Overview

pg_walviz presents the same WAL data at three synchronized levels:

  • The segment overview locates WAL activity and summarizes parsed records by resource manager.
  • WAL Record Fragments lists every record portion stored on the selected page and supports direct page and record-number navigation.
  • The record inspector and Physical Bytes view expose decoded record components, block references, full-page images, padding, and raw bytes.

Selecting a page, record fragment, or physical byte updates the other views. Hover over a byte for its value, LSN, page, record, fragment, and decoded component context.

pg_walviz overview

No PostgreSQL server or data directory is required. A version-matched pg_waldump executable is recommended for resource-manager record names and descriptions.

Requirements

  • Python 3.7 or newer
  • WAL segment files from one PostgreSQL cluster and one timeline
  • The matching PostgreSQL pg_waldump executable for logical descriptions

The viewer has no browser-side packages and does not upload WAL data.

Run

Warning

Do not use the current, actively written WAL segment, and do not point pg_walviz at the pg_wal directory of a running server. Metadata is parsed at startup, while the hex pane reads the source files later. If a source changes, the decoded metadata and displayed bytes can disagree. Use completed archived segments or immutable copies instead.

Pass a segment file:

~/pg_walviz/bin/pg_walviz \
  --pg-waldump /path/to/matching/postgres/bin/pg_waldump \
  /archive/000000010000000000000042

Directories are also accepted:

~/pg_walviz/bin/pg_walviz \
  --pg-waldump /path/to/matching/postgres/bin/pg_waldump \
  /archive/wal/

A PostgreSQL data directory is accepted only when the server is stopped and its WAL files cannot change. For a running server, use an archive directory or copy completed segments elsewhere first.

The server binds to 127.0.0.1 on an automatically selected port and opens the local URL. In a headless or remote environment:

~/pg_walviz/bin/pg_walviz --no-open --port 8765 \
  --pg-waldump /path/to/matching/postgres/bin/pg_waldump \
  /archive/000000010000000000000042

Then forward the port from a workstation:

ssh -N -L 8765:127.0.0.1:8765 user@server

Use --pg-waldump none when only physical decoding is required.

Views

The four views stay synchronized: selecting a page or record in one updates the others.

Segment overview

Segment overview heatmap

The heatmap shows where each resource manager writes WAL. Color intensity represents record-byte density. Click a cell to inspect it, or drag across pages to zoom. The Summary tab reports record and full-page-image bytes by resource manager.

WAL Record Fragments

WAL Record Fragments

This view lists the records stored on the selected WAL page. A record spanning several pages appears once on each page. Use the page and record fields for direct navigation, or the left pane to filter the list.

Selected Record

Selected Record

The inspector decodes the selected record's header, physical layout, block references, full-page images, CRC, and pg_waldump description.

Physical Bytes

Physical Bytes

This view displays the raw WAL bytes with colors matching the selected record's physical layout. Hover over a byte for its value, location, record, fragment, and decoded component.

Heatmap and Summary statistics exclude page headers, alignment padding, zero-fill, and unparsed ranges. In Summary, record bytes exclude stored full-page-image payloads, while combined bytes include them.

Zero bytes are labeled as padding only when record alignment proves that classification. Other zero-filled ranges remain distinct from alignment padding because they may be segment tail space or unused pages.

Page numbers are zero-based indexes within a segment. Record numbers are zero-based viewer indexes assigned in parse order across the supplied input set; they are not identifiers stored in WAL and can change when the input set changes.

Compatibility and limitations

pg_walviz is a diagnostic visualizer, not a replacement for PostgreSQL recovery, XLogReader, or pg_waldump. A clean visualization and valid CRCs do not prove that WAL is semantically correct or replayable.

PostgreSQL format and build

  • The physical parser has explicit profiles for PostgreSQL 14 through the current PostgreSQL 20 development format:

    PostgreSQL WAL page magic
    14 0xD10D
    15 0xD110
    16 0xD113
    17 0xD116
    18 0xD118
    19 / 20devel 0xD121
  • PostgreSQL 19 and the current 20devel tree share the same generic WAL format and page magic, so a segment alone cannot distinguish them. The viewer reports PostgreSQL 19 or 20devel.

  • WAL page magic, byte order, WAL page size, and segment size are detected from the long page header. Unknown magic values are rejected instead of being parsed with a guessed format.

  • Profiles select the version-specific page flags, full-page-image flags, compression methods, and built-in resource-manager IDs. The fixed record and block-reference structures are shared where PostgreSQL keeps them byte-compatible.

  • The 20devel profile describes the source tree at the time of this release. A later development change can bump the page magic and require a new profile.

  • Record alignment currently assumes an 8-byte MAXALIGN. Padding annotations are wrong for a build with a different MAXIMUM_ALIGNOF.

  • Full-page-image hole calculations assume the data page size (BLCKSZ) is the standard 8 KiB WAL page size reported in the long header. A custom --with-blocksize build can produce incorrect hole lengths because WAL does not record BLCKSZ there.

  • Full-page images are located and their compression method and hole metadata are reported, but images are not decompressed, reconstructed, or validated as PostgreSQL data pages.

  • Only plain WAL segment files with standard uppercase names, optionally with a .partial suffix, are discovered. Compressed or packaged archives must be extracted first.

Use the exact pg_waldump built for the WAL-producing PostgreSQL version and build. A matching pg_waldump improves descriptions but does not change the physical parser's assumptions.

Input set and continuity

  • Supply files from one PostgreSQL system identifier and one timeline only. The tool displays these values but does not currently enforce consistency across every input file.
  • Do not combine timeline branches. Internal page and description indexes use LSNs without a timeline component, so equal LSNs from different timelines can collide.
  • Consecutive segments are required to reconstruct records crossing a segment boundary. If the first supplied segment begins with a continuation, the partial record that started in the previous segment cannot be decoded.
  • A record extending beyond the last supplied segment is reported as incomplete. Subsequent bytes cannot be interpreted without the next segment.
  • .partial files can be inspected physically, but an incomplete final record is expected and pg_waldump enrichment may be unavailable or partial.
  • Directory input selects every matching WAL filename. Select a small, deliberate set instead of an entire archive unless the resource cost is acceptable.

Parsing and validation

  • The native parser decodes the generic WAL envelope: page headers, record headers, block references, images, block data, main data, continuations, alignment, and CRC32C. It does not decode resource-manager-specific binary payloads, tuples, catalog contents, or relation names.
  • Relation references remain numeric tablespace/database/relfilenode values. No catalog lookup is performed.
  • Validation covers page-header geometry, continuation lengths, fragment accounting, generic record layout, and record CRC32C as described below. It does not validate the xl_prev chain, timeline history, pg_control, replay semantics, or consistency between resource-manager payloads and referenced pages.
  • CRC32C is not calculated natively for every record during startup. Records successfully emitted by pg_waldump are marked as CRC-valid because PostgreSQL validates them before returning them. An unmatched record remains not checked until it is selected, at which point the viewer calculates its CRC32C directly from its physical fragments.
  • CRC32C covers WAL record bytes, not alignment padding. A valid CRC does not validate padding bytes or prove that the record can be replayed.
  • Parsing stops at the first zero or invalid record length in each contiguous input group. The tool does not scan ahead to resynchronize after corruption, so valid records later in the segment may not be shown.
  • Overwrite-continuation records and corruption recovery are not fully modeled. They may terminate parsing and leave the remainder marked unparsed.
  • Alignment padding is inferred from the record end and MAXALIGN, regardless of the bytes stored there. It is not inferred from zero values.
  • zero-fill means only that an unclassified physical range contains zero bytes. It does not prove why the range is unused. Segment-switch tail space is not distinguished from other zero-filled tail space.

pg_waldump enrichment

  • pg_waldump is invoked once per segment during startup, plus once with --version. Browser actions never invoke it.
  • If --pg-waldump is omitted, the first executable named pg_waldump on PATH is used. Its reported version is displayed but is not checked against the segment's page magic or build parameters.
  • Its human-readable output is parsed with a regular expression and matched to native records by LSN. PostgreSQL output-format changes can cause missing or partial descriptions.
  • A record matched to pg_waldump output is also marked CRC-valid. Records that pg_waldump does not reach or describe remain not checked until selected.
  • pg_waldump errors do not discard successfully parsed physical metadata. Descriptions can therefore be only partially populated.
  • Custom resource managers may remain named by numeric ID and may not have a useful description.
  • Use --pg-waldump none to disable enrichment. Physical structure remains available, subject to the parser assumptions above.

Resource usage and browser behavior

  • All selected segment contents are read into memory before physical parsing. Compact record summaries, fragment indexes, regions, and captured pg_waldump output require additional server memory.
  • The initial browser snapshot contains segment summaries, pages, heatmap bins, special regions, and diagnostics. It does not contain the full record index.
  • Fragment metadata is loaded when a page is selected. The All pages view requests filtered, paginated windows. Full record components and block references are reconstructed from the WAL bytes only when that record is selected.
  • For large input, inspect one segment file at a time rather than an entire directory. --pg-waldump none avoids description enrichment and can reduce server startup time and memory.
  • The heatmap compresses many pages and records into the available screen width. A visible cell can represent multiple physical objects; drag across a range to re-bin and zoom it, then use page selection and Physical Bytes for exact inspection.
  • Large segment sizes, many segments, or WAL containing many small records can still cause long server startup times and high server memory use. Metadata loading reduces initial JSON transfer and browser memory; it does not make physical parsing or pg_waldump enrichment lazy. The current implementation is intended for focused inspection of a small number of segments.
  • The viewer requires a modern browser with JavaScript modules, BigInt, fetch, canvas, CSS color-mix(), and HTTP range support.

HTTP and data exposure

  • The HTTP server has no authentication, authorization, or TLS. Keep the default loopback binding and use an SSH tunnel for remote access.
  • Anyone able to reach the server can request raw WAL byte ranges and metadata, including source filesystem paths.
  • WAL and pg_waldump descriptions can expose table contents, credentials, logical messages, and other sensitive values.

Input safety

pg_walviz opens segment files read-only, but read-only access does not make the source files stable. It parses metadata during startup and later reopens the source files for hex range requests. You must not use an actively written segment. Doing so can produce misleading metadata, mismatched hex bytes, or transient CRC and page-header diagnostics.

On a running server, identify the current segment with:

SELECT pg_walfile_name(pg_current_wal_lsn());

Do not visualize that filename directly from the live pg_wal directory. To complete the current segment first:

SELECT pg_switch_wal();

Then use a completed segment older than the new current segment, preferably from the WAL archive or from an immutable copy. Older files in live pg_wal can also be recycled, so the archive or a separate copy is safer.

WAL can contain table data, credentials, and other sensitive values. The HTTP server listens on loopback by default; avoid binding it to an untrusted network.

Development

Run the dependency-free test suite:

make check

The synthetic tests build WAL bytes directly and do not initialize or start a PostgreSQL instance.

License

Copyright (c) 2026, pg_walviz contributors.

pg_walviz is free software licensed under the GNU General Public License version 2 or later.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages