> ## Documentation Index
> Fetch the complete documentation index at: https://xata.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# v1.2.0

> pgstream v1.2.0 release notes

**Release Date:** July 15th, 2026

pgstream v1.2.0 is a minor release built around catching problems before a migration starts rather than during it. It introduces the experimental `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](https://github.com/xataio/pgstream/pull/901) and follow-ups, by [@kvch](https://github.com/kvch), with contributions from [@kv1sidisi](https://github.com/kv1sidisi) and [@lghuy05](https://github.com/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:

```bash theme={null} theme={null}
pgstream check -c pg2pg.yaml
pgstream check -c pg2pg.env --json
```

Checks are grouped into five categories — `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](https://github.com/xataio/pgstream/pull/902), [PR #905](https://github.com/xataio/pgstream/pull/905)).
* **Replication.** `wal_level`, slot availability and related replication prerequisites ([PR #904](https://github.com/xataio/pgstream/pull/904)), plus replica identity ([PR #911](https://github.com/xataio/pgstream/pull/911)).
* **Access.** `SELECT` privileges on the source tables ([PR #912](https://github.com/xataio/pgstream/pull/912)) and on sequences ([PR #947](https://github.com/xataio/pgstream/pull/947)), both contributed by [@lghuy05](https://github.com/lghuy05). Schema, table and role identifiers are quoted in the messages ([PR #944](https://github.com/xataio/pgstream/pull/944)).
* **Schema.** Schema compatibility validation, contributed by [@kv1sidisi](https://github.com/kv1sidisi) ([PR #896](https://github.com/xataio/pgstream/pull/896)), moved into preflight ([PR #951](https://github.com/xataio/pgstream/pull/951)), plus source/target extension compatibility ([PR #952](https://github.com/xataio/pgstream/pull/952)).
* **Resources.** A new category covering resource limits on the source and target ([PR #971](https://github.com/xataio/pgstream/pull/971)).

The command is experimental: the checks and their output format may change in later releases.

## New `encrypted_aes_siv` Transformer

[PR #998](https://github.com/xataio/pgstream/pull/998), contributed by [@geo-ocean](https://github.com/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:

```yaml theme={null} theme={null}
transformations:
  table_transformers:
    - schema: public
      table: orders
      column_transformers:
        file_path:
          name: encrypted_aes_siv
          parameters:
            key_hex: "${PGSTREAM_AES_KEY}" # 64-byte key, hex-encoded
            associated_data: "public.orders.file_path"
```

Because it is reversible by anyone holding `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](https://github.com/xataio/pgstream/pull/999), by [@tsg](https://github.com/tsg), with the underlying table selection in [PR #949](https://github.com/xataio/pgstream/pull/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:

```yaml theme={null} theme={null}
source:
  postgres:
    snapshot:
      tables: ["*.*"]
      schema_only_tables: ["audit_log", "reports.*"]
```

The same list exists as a filter for the streaming side, where DDL events are processed and DML events are skipped. This is what large append-only audit tables need: the target keeps a usable schema without paying to copy history.

## Parallelized COPY Workers

[PR #995](https://github.com/xataio/pgstream/pull/995), by [@kvch](https://github.com/kvch).

Bulk ingest opens several concurrent COPY streams per table instead of one, governed by `copy_workers` (default 8):

```yaml theme={null} theme={null}
target:
  postgres:
    bulk_ingest:
      enabled: true
      copy_workers: 8
```

## Configurable Transformer Error Policy

[PR #958](https://github.com/xataio/pgstream/pull/958), by [@kvch](https://github.com/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`:

```yaml theme={null} theme={null}
modifiers:
  transformations:
    on_error: fail
```

Note that `pass-through` emits unanonymized data on failure, which is rarely what an anonymization pipeline wants.

## Strict Mode for Dropped Writes

[PR #959](https://github.com/xataio/pgstream/pull/959), by [@kvch](https://github.com/kvch), and [PR #976](https://github.com/xataio/pgstream/pull/976), contributed by [@danddanddand](https://github.com/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:

```yaml theme={null} theme={null}
target:
  postgres:
    strict_mode: true
```

A counter for dropped messages ships with it, so the non-strict path is measurable rather than only visible in logs.

## Nightly and Container Image Releases

[PR #955](https://github.com/xataio/pgstream/pull/955) and [PR #980](https://github.com/xataio/pgstream/pull/980), by [@kvch](https://github.com/kvch).

Container images are built and published automatically with build provenance and SBOM attestations, and a nightly release is published from `main` for testing unreleased fixes.

## Other Improvements

* **SQL parameter binding and escaping** in the replication path ([PR #965](https://github.com/xataio/pgstream/pull/965)). Also released on the 0.9 line as [v0.9.15](https://github.com/xataio/pgstream/releases/tag/v0.9.15).
* **Postgres temp schemas are excluded** from snapshot discovery ([PR #954](https://github.com/xataio/pgstream/pull/954)), contributed by [@danddanddand](https://github.com/danddanddand).
* **Legacy `public` PL/pgSQL handler functions are skipped** on snapshot restore ([PR #906](https://github.com/xataio/pgstream/pull/906)).
* **pgstream metadata DML is skipped** for Postgres targets ([PR #977](https://github.com/xataio/pgstream/pull/977)), contributed by [@danddanddand](https://github.com/danddanddand).
* **`validate` exits 1 when validation fails** ([PR #948](https://github.com/xataio/pgstream/pull/948)), contributed by [@fiws](https://github.com/fiws), so it can be used in CI.
* **Log level reloads on `SIGHUP`** ([PR #945](https://github.com/xataio/pgstream/pull/945)), contributed by [@pollychen-lab](https://github.com/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](https://github.com/xataio/pgstream/pull/950)), the log level is checked before logging ([PR #969](https://github.com/xataio/pgstream/pull/969)), and DDL events are converted once per event in the processor chain ([PR #970](https://github.com/xataio/pgstream/pull/970)).

## Bug Fixes

* **Top-level JSONB `null` values** are treated correctly instead of being confused with a SQL NULL ([PR #991](https://github.com/xataio/pgstream/pull/991)), by [@tsg](https://github.com/tsg).
* **`exclude_tables` across multiple schemas** no longer excludes the wrong tables ([PR #992](https://github.com/xataio/pgstream/pull/992)), by [@tsg](https://github.com/tsg).
* **`snapshot` CLI auto-enables bulk ingest** when the corresponding flags are used ([PR #993](https://github.com/xataio/pgstream/pull/993)).
* **Batch sender startup race** between `NewSender` and `Close` ([PR #994](https://github.com/xataio/pgstream/pull/994)).
* **Data race in the batch-bytes auto-tuner** ([PR #957](https://github.com/xataio/pgstream/pull/957)).
* **Backoff `MaxInterval` was wired to `MaxElapsedTime`** ([PR #956](https://github.com/xataio/pgstream/pull/956)), so retry intervals grew far past their configured ceiling.
* **`GetTables` shadowed the outer result slice** during snapshots ([PR #960](https://github.com/xataio/pgstream/pull/960)).

## New Contributors

* [@kv1sidisi](https://github.com/kv1sidisi) in [PR #896](https://github.com/xataio/pgstream/pull/896)
* [@lghuy05](https://github.com/lghuy05) in [PR #912](https://github.com/xataio/pgstream/pull/912)
* [@pollychen-lab](https://github.com/pollychen-lab) in [PR #945](https://github.com/xataio/pgstream/pull/945)
* [@geo-ocean](https://github.com/geo-ocean) in [PR #998](https://github.com/xataio/pgstream/pull/998)

## Upgrade

No configuration changes are required, and no re-initialization is needed. Replace the binary and restart pgstream. The `check` 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](https://github.com/xataio/pgstream/issues)
* Documentation: [https://github.com/xataio/pgstream/tree/main/docs](https://github.com/xataio/pgstream/tree/main/docs)
* Discussions: [https://github.com/xataio/pgstream/discussions](https://github.com/xataio/pgstream/discussions)
