Skip to main content
Release Date: August 4th, 2026 pgstream v1.3.1 is a patch release about snapshots taken while the source schema is moving. The data snapshot now reads the columns the schema snapshot captured, so a column added mid-snapshot no longer breaks the load, and drift that the pin cannot absorb is reported instead of silently applied. It also adds a CREATEDB preflight check for snapshots that create the target database, and documents how DDL replication can carry privileges from a less trusted source to the target. No migration is required.

Snapshot Column Pinning

PR #1058, with catalog helpers in PR #1057, by @kvch. The data snapshot read rows with SELECT * FROM ONLY <table> WHERE ctid BETWEEN '(x,0)' AND '(y,0)'. SET TRANSACTION SNAPSHOT pins row visibility, but not the catalog, and every page range plans its own query — so the column list was re-resolved from the live source catalog throughout the snapshot, while the target’s schema stayed as the schema dump had left it. A column added to the source once the dump was done appeared in the reads of every page range planned after it, and those rows carried a column the target did not have. Each table’s read is now pinned to the columns the schema snapshot captured. pg_dump is preceded by a catalog read that records the column list of every table in the dump’s scope, and the page range queries spell those columns out instead of *, so a column added afterwards is simply not read. The ADD COLUMN and any backfill arrive over the replication stream, which already starts from an LSN taken before the snapshot. A snapshot with no schema dump — schema-only runs, or a data snapshot configured on its own — captures nothing and keeps reading * as before.

Schema Drift Is Reported Rather Than Absorbed

The pin narrows the window but does not remove it: the capture and the dump are two separate reads of the source. After the dump, the columns are read again and any table that changed in between is named in a warning, since it may be snapshotted with stale columns and needs replication to converge — or a re-snapshot if none follows. A column dropped after the capture is dropped from the read too, so the rest of the table still loads. If none of a table’s captured columns still exist, the table snapshot fails with source schema changed during the snapshot rather than falling back to SELECT *, which would reintroduce the bug for that table. A table dropped mid-snapshot now reports the same error instead of a bare relation does not exist. A table that the capture did not see — created after it, or a name that did not resolve to a catalog entry — is logged and read with the columns it has now.

CREATEDB Preflight Check

PR #996, contributed by @lghuy05. pgstream check verifies that the target role can create databases when the snapshot is configured to create the target database:
The check reads rolcreatedb from pg_roles for the current target session role and reports an actionable finding when the privilege is missing, instead of the run failing at restore time. It is registered only when create_target_db is enabled for a Postgres target.

DDL Replication and Trust Domains

PR #1052, by @tsg. DDL captured on the source is replayed on the target as the pgstreamtarget role, which means pgstream assumes source and target are in one trust domain. Where they are not — roles that can run DDL on the source being less trusted than pgstreamtarget — those roles can get SQL executed on the target with the target role’s privileges. docs/privileges.md now says so, and recommends granting pgstreamtarget only what it needs (no SUPERUSER, CREATEROLE or CREATEDB unless a feature requires it), or disabling DDL replication with ignore_ddl where the trust levels differ.

Upgrade

No configuration changes are required, and no re-initialization or migration is needed. ⚠️ If you snapshot a source that receives DDL. Snapshots run before this release may have loaded rows shaped by a column list that changed underneath them; a table that failed to write mid-snapshot for a column the target did not have needs a re-snapshot. Going forward, watch for the two new signals: the drift warning naming tables that changed during the dump, and source schema changed during the snapshot, which aborts that table’s snapshot. Snapshots that previously ran to completion can now fail. The source schema changed during the snapshot error is new: a table whose captured columns have all been dropped, or that was dropped outright, now stops rather than reading whatever the source has at that moment. This is the intended outcome — the alternative silently produces a table the target cannot accept — but a pipeline that snapshots concurrently with heavy DDL will surface it as a table-level failure that did not exist before. Preflight. pgstream check with create_target_db: true now runs one additional query against the target and reports a finding if the role lacks CREATEDB. Targets already holding the privilege see no change beyond an extra passing check in the output.

Support