check command, which runs preflight validation of connectivity, replication, access, schema and resources against the source and target. Alongside it: a deterministic encrypted_aes_siv transformer, schema-only tables, parallelized COPY workers for faster snapshots, a configurable transformer error policy, a strict mode that fails snapshots on dropped Postgres writes, and automated nightly and container image releases. No migration is required.
New check Command
PR #901 and follow-ups, by @kvch, with contributions from @kv1sidisi and @lghuy05.
pgstream check runs preflight validation against the configuration you are about to run, and reports what would block a snapshot or a replication run:
connectivity, replication, access, schema and resources — and the command exits non-zero when any check fails, so it can gate a deployment.
What ships in this release:
- Connectivity. Source and target Postgres reachability (PR #902, PR #905).
- Replication.
wal_level, slot availability and related replication prerequisites (PR #904), plus replica identity (PR #911). - Access.
SELECTprivileges on the source tables (PR #912) and on sequences (PR #947), both contributed by @lghuy05. Schema, table and role identifiers are quoted in the messages (PR #944). - Schema. Schema compatibility validation, contributed by @kv1sidisi (PR #896), moved into preflight (PR #951), plus source/target extension compatibility (PR #952).
- Resources. A new category covering resource limits on the source and target (PR #971).
New encrypted_aes_siv Transformer
PR #998, contributed by @geo-ocean.
A deterministic authenticated-encryption transformer based on AES-SIV (RFC 5297). The same input, key and associated data always produce the same token, so equality relationships survive across rows, tables and runs — which makes it the transformer to reach for on a column covered by a unique index or used as a join key:
key_hex, it is pseudonymization rather than anonymization: keep the key in a secret store, use a different key per environment, and set associated_data so tokens cannot be correlated between columns. Tokens are longer than their input, so length-constrained columns must be wide enough to hold them.
Schema-Only Tables
PR #999, by @tsg, with the underlying table selection in PR #949. Tables can be replicated as structure without data. On the snapshot side,schema_only_tables restores the table definition and copies its sequence values but skips the rows:
Parallelized COPY Workers
PR #995, by @kvch. Bulk ingest opens several concurrent COPY streams per table instead of one, governed bycopy_workers (default 8):
Configurable Transformer Error Policy
PR #958, by @kvch. What happens when a transformer fails on a value is now a choice rather than a fixed behaviour.on_error accepts fail (stop the pipeline), pass-through (emit the original value) or null:
pass-through emits unanonymized data on failure, which is rarely what an anonymization pipeline wants.
Strict Mode for Dropped Writes
PR #959, by @kvch, and PR #976, contributed by @danddanddand. The Postgres target can drop a failing query and continue, which keeps a pipeline alive at the cost of silent divergence.strict_mode stops the pipeline instead, and snapshots now fail when a write is dropped:
Nightly and Container Image Releases
PR #955 and PR #980, by @kvch. Container images are built and published automatically with build provenance and SBOM attestations, and a nightly release is published frommain for testing unreleased fixes.
Other Improvements
- SQL parameter binding and escaping in the replication path (PR #965). Also released on the 0.9 line as v0.9.15.
- Postgres temp schemas are excluded from snapshot discovery (PR #954), contributed by @danddanddand.
- Legacy
publicPL/pgSQL handler functions are skipped on snapshot restore (PR #906). - pgstream metadata DML is skipped for Postgres targets (PR #977), contributed by @danddanddand.
validateexits 1 when validation fails (PR #948), contributed by @fiws, so it can be used in CI.- Log level reloads on
SIGHUP(PR #945), contributed by @pollychen-lab, for turning on debug logging without a restart. - Hot-path performance: column types and timestamps are resolved once per result set (PR #950), the log level is checked before logging (PR #969), and DDL events are converted once per event in the processor chain (PR #970).
Bug Fixes
- Top-level JSONB
nullvalues are treated correctly instead of being confused with a SQL NULL (PR #991), by @tsg. exclude_tablesacross multiple schemas no longer excludes the wrong tables (PR #992), by @tsg.snapshotCLI auto-enables bulk ingest when the corresponding flags are used (PR #993).- Batch sender startup race between
NewSenderandClose(PR #994). - Data race in the batch-bytes auto-tuner (PR #957).
- Backoff
MaxIntervalwas wired toMaxElapsedTime(PR #956), so retry intervals grew far past their configured ceiling. GetTablesshadowed the outer result slice during snapshots (PR #960).
New Contributors
- @kv1sidisi in PR #896
- @lghuy05 in PR #912
- @pollychen-lab in PR #945
- @geo-ocean in PR #998
Upgrade
No configuration changes are required, and no re-initialization is needed. Replace the binary and restart pgstream. Thecheck command, encrypted_aes_siv, schema-only tables and strict mode are all opt-in.
Scripts that call pgstream validate should be aware that it now exits with code 1 when validation fails, where it previously exited 0.
Support
- Issues: https://github.com/xataio/pgstream/issues
- Documentation: https://github.com/xataio/pgstream/tree/main/docs
- Discussions: https://github.com/xataio/pgstream/discussions