xataio / xataio/pgstream

Add `pgstream check` command for pre-migration sanity checks

Open
#897 1 comment 3 reactions 1 assignee View on GitHub

@kvch is already working on this.

Since Jun 19, 2026.

enhancement
Dominant language
Go
Stars
1.2k
Forks
82
Avg merge
18h 22m
Merged PRs (30d)
51

Description

Problem

A pgstream migration can fail many hours in:

  • a REPLICA IDENTITY misconfiguration that only shows up the first time an UPDATE flows
  • an extension missing on the target that pg_restore only notices at COPY time
  • the replication role missing the REPLICATION attribute
  • max_replication_slots already exhausted
  • a target Postgres version that can't accept some syntax the source uses
  • a column type pgstream can't decode buried inside an otherwise-clean schema
  • max_connections too low for the configured worker count

Users who've already spent 10+ hours waiting for a snapshot or replication catch-up shouldn't be discovering setup issues at hour 10 that could have been flagged in 30 seconds before anything ran.

Requirements

  • A single CLI invocation runs every applicable check using the same configuration source as run or snapshot.
  • Each finding has severity (error / warning / info) and an actionable message.
  • Inapplicable checks (e.g. CREATEROLE when roles_snapshot_mode: disabled) are skipped with a one-line reason.
  • Exit codes: 0 clean, 1 error-tier findings, 2 validator failure. --strict upgrades warnings to errors.
  • Output supports human-readable and --json formats.

Solution

Add a pre-migration check (working name: pgstream check) that runs every check that can be answered statically (connectivity, privileges, version, replication setup, schema compatibility, resource capacity) and returns a structured report.

The command reads the same YAML/env/flag configuration that pgstream run and pgstream snapshot consume, so users can validate the exact config they're about to migrate with.

Exit codes mirror validate rules: 0 clean, 1 blocking findings, 2 validator itself failed. --json produces a machine-readable report; default is human-readable with severity-tagged sections.

Checks to run

Connectivity & identity @kvch
  • Source is reachable
  • Target is reachable
  • Source and target are not the same host/database (catches accidental same-DB config)
  • Source and target Postgres versions are compatible (target >= source; flag known cross-version pitfalls)
Replication setup @kvch
  • wal_level = logical on source
  • wal2json is installed and loadable on source
  • At least one replication slot is available (pg_replication_slots vs max_replication_slots)
  • Source role has the REPLICATION attribute
  • Per-table REPLICA IDENTITY is sufficient for UPDATE/DELETE replication (default + PK, or FULL, or explicit USING INDEX)
  • Tables without a primary key or usable unique constraint are listed up front
  • List tables that won't be replicated and why (foreign tables, materialized views, unlogged tables, partitioned parents without leaves, etc.)
Access & privileges @lghuy05
  • Source role has SELECT on all in-scope tables
  • Source role can read all in-scope sequences
  • If create_target_db: true: target admin role has CREATEDB
  • If roles_snapshot_mode is enabled or no_passwords: target admin role has CREATEROLE
  • If no_owner: false: source role has the rights needed to preserve ownership on the target (target role exists or can be created)
Schema compatibility @kvch
  • All in-scope column types can be decoded by pgstream (mapper coverage)
  • Extensions used by in-scope columns are installed on the source
  • Extensions used by in-scope columns are installed (or installable) on the target
  • All sequences referenced by in-scope tables exist on the source and are reachable
Resources
  • Source can serve snapshot_workers × table_workers concurrent connections without exceeding max_connections (account for existing usage, superuser slots reserved by superuser_reserved_connections)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.