v0.1.0
First release of pg-sprite — an online schema-change engine for PostgreSQL that classifies every DDL operation before running it, substitutes the safer native form where one exists, and refuses honestly (with typed guidance) where it doesn't.
Highlights
Planner: classify first, never guess
- All SQL enters through one parse boundary using the real PostgreSQL grammar —
libpg_querycompiled to Wasm (wasilibs/go-pgquery), so a parse failure is a typed error, never a guess, and builds stay pure Go. (#6) - The declarative diff is derived by execute-and-introspect — desired DDL runs in a transaction-scoped scratch schema and the model is read back from PostgreSQL's own catalogs, then rolled back; no reimplementation of PostgreSQL's semantics to drift out of date. (#6, #20)
- Every operation is classified native-safe · needs-rewrite · refuse before anything runs — the classifier and router are the one place the safety decision lives, and both front doors (imperative
--alter, declarative--desired) converge on the same pipeline. (#7) - One versioned plan report for both front doors —
diffandmigrate --dry-runemit the same machine-readable plan (format_version: 2), with typed guidance on rewrite-required statements. (#8, #37) - Column and table renames classify as app-breaking — a rename is an application contract change, not a metadata tweak, and the verdict says so. (#19)
Execution: the safer form by default
- The optimistic front door commits instant changes and refuses the rest with typed verdicts — a metadata-only change just runs; anything else gets a
not-native-safeverdict naming the reason. (#5) - Blocking forms are substituted with the safer native sequence by default —
CREATE INDEXruns asCREATE INDEX CONCURRENTLY,ADD CONSTRAINT UNIQUEbuilds the index concurrently first; overriding requires a typed--forceacknowledgement naming the exact target table. (#28, #30, #32) CREATE INDEX CONCURRENTLYrecovers fail-closed — a failed concurrent build detects the invalid index and cleans up rather than leaving it behind. (#15)- Every statement runs under bounded
lock_timeoutwith bounded retry — DDL that cannot get its lock backs off and retries a bounded number of times instead of queueing behind traffic. (#27) - Preflight names the exact missing GRANTs — an engine role without the needed privileges gets a typed refusal listing the GRANT statements to run, before any DDL is attempted. (#31)
- Parent-level index builds on partitioned tables are refused — the unsupported partitioned-parent case fails closed instead of taking locks it cannot honor. (#33)
- Execution progress is machine-readable across strategies — a strategy-wide
Progress()contract backed bypg_stat_progress_create_indexand sequence step position. (#41)
CLI: compiler-grade diagnostics
migrate --dry-run,diff,lint, andsuggestrender as colored compiler-style diagnostic reports — with a stable exit-code contract, and--jsoneverywhere for machines; the raw SQL script moved behind--sql. (#36, #43, #46)lintproduces offline typed findings — file/line/column, severity, reason codes, and the safer form inline. (#9)suggestrecommends safer native forms with typed caveats — and is explicit that a safer form is not a semantic equivalent. (#13, #14)- A runnable demo tour doubles as the artifact smoke test —
make demowalks the CLI the way a user invokes it; VHS-generated terminal GIFs are committed with their tapes. (#39, #42)
Testing: real databases, all supported majors
- The full suite runs against real PostgreSQL 14 → 18 — integration tests via testcontainers, with the version matrix as a merge gate. (#3, #4, #21)
- An AWS-boundary test tier via Ministack — RDS/Aurora API fidelity, managed-password rotation reconnects, and control-plane error contracts are exercised in CI without touching AWS. (#11, #12, #25, #29)
- Docs-only changes skip the test matrix — with exclusion patterns that are themselves tested. (#23)
Docs
- Vision, architecture, and low-level design ship with the code — including the SchemaBot integration contract, the engine-role provisioning contract (tiered access for schema changes), and a README written as decided outcomes with demo GIFs. (#2, #10, #17, #18, #22, #24, #35, #40, #44, #45)
Upgrade notes
- First tagged release. The module is
github.com/block/pg-sprite; the CLI installs via the attached binaries orgo install github.com/block/pg-sprite/cmd/pg-sprite@v0.1.0. - The plan report is
format_version: 2and verdicts carry typedguidance. Consumers pinning pre-release pseudo-versions should re-validate their plan/verdict mapping when moving to the tag. (#37, #38) - This release requires Go 1.26. Consumers embedding the module must be on that toolchain or newer.
Contributors
Full Changelog: https://github.com/block/pg-sprite/commits/v0.1.0