Handling a new PostgreSQL release
What has to happen in PlumeSQL when PostgreSQL ships a new major, in the order that keeps every step verifiable, plus the inventory of every version-sensitive surface so nothing is discovered by a user first. Written 2026-08 with 13 through 18 supported; the steps are the same for every future major.
What "supported" means here
PlumeSQL supports a contiguous range of majors: the oldest release the snapshot renders correctly through the newest one the test matrix proves. The range lives in exactly three places, and they must agree:
scripts/pgmatrix.sh(the VERSIONS default): whatmake test-versionsboots locally..github/workflows/schema-matrix.yml: one service container per version plus the port spec line, the CI copy of the same matrix.web/src/lib/pgsql-versions.ts: the newest major with a grammar delta entry (newestKnownfollows the delta table).
A server NEWER than the newest known major is not refused anywhere: the editor grammar gives it every delta it has (languageFor treats an unknown major as "all of them"), the snapshot renders what the catalog offers, and whatever is wrong surfaces in the matrix once the version is added. Support is therefore a statement about what is TESTED, not a gate.
The checklist for a new major NN
Do the steps in this order: each one's verification depends on the one before it.
Read the release notes first, with four questions: new SQL syntax and keywords (grammar deltas), catalog changes (search.sql), new object families or properties (snapshot CTEs and the dictionary), and pg_dump or psql behavior changes (the backup modal and the replay half of the matrix). PostgreSQL's own
src/include/parser/kwlist.hdiff between NN-1 and NN is the authoritative keyword list.Add NN to the test matrix and make it pass. Add the version to
scripts/pgmatrix.shVERSIONS, apostgres:NN-alpineservice toschema-matrix.ymlwith its port in the spec line, then runmake test-versions. This is the only thing that checks the four properties nothing else can: every rendered file executes again on the server it came from, a snapshot of the replayed database equals the original byte for byte, the dictionary matches the catalog, and nothing flaps between two renders. Fixsearch.sqlwhere NN moved a catalog column or changed a render function's output; a genuinely new object family gets its own CTE, its dictionary entry (docs/OBJECTINDEX.md in the same change) and amatrix_fixture.sqlblock declaringmin=NN. A beta can be run through the same matrix without committing anything:PLUMESQL_PG_VERSIONS="18 19" make test-versions.Add the editor grammar delta. One entry in
web/src/lib/pgsql-versions.tsdeltas: the keywords, builtin functions and type keywords NN introduced (from step 1's kwlist diff). This is what makes a new keyword light up only on servers that can run it, and what feeds completion's keyword lists. The per-version reserved-word comment inpgsql.tssays how reserved words are handled; touch it only if NN reserves a formerly unreserved word.Refresh the tree-sitter grammar asset once upstream (gmr/tree-sitter-postgres, generated from PostgreSQL's own gram.y) lands the NN grammar. The rebuild steps live in
web/public/treesitter/README.mdbeside the asset (git-lfs clone,tree-sitter build --wasm,gzip -9); update that README's provenance commit in the same change. Deliberate design: ONE grammar tracking the newest release serves every server, because a newer grammar parses older SQL (supersets), and any gap while upstream catches up costs only completion scope and formatting for the new syntax, never correctness: the formatter refuses what does not parse and completion falls back to the sqlcontext.ts heuristics.Check the client tools story. Dumps (the backup modal, the snapshot's pg_dump paths) need pg_dump >= the server's major;
pg_dump --versionolder than NN refuses an NN server. The System page's tool install should offer a version that covers NN, and the version-mismatch wording in the dump flows should stay truthful. psql needs nothing.Spot-check what needs no change, so it stays that way. pgdocs.ts builds
postgresql.org/docs/<major>/URLs from the server's own major, so new docs links work the day NN ships (only a renamed page would need the keyword-to-page map touched). pgx handles the wire protocol viamake upgrade-go. The Activity and Top queries panels read pg_stat_activity and pg_stat_statements, whose shapes DO occasionally move between majors: run both against an NN server once.Bump the disposable containers when NN becomes the new stable: the dev container line in AGENTS.md and the e2e-db container in the Makefile (
postgres:NN-alpine). Not a correctness matter (the matrix covers every version), just keeping daily development on a current server.Manual pass and the changelog. Connect to an NN server and walk the surfaces that read the catalog live: object tree and dictionary (refresh a snapshot), completion with and without the parser, statement marks, Activity, Top queries, a backup and a restore. Then one CHANGELOG line under Unreleased naming the supported range, since a new supported major is a user-visible change.
Dropping an old major
A deliberate decision, never a side effect, and lazier than PostgreSQL's own EOL calendar (13 went EOL in late 2025 and is still supported here because supporting it costs almost nothing). When one is dropped: remove it from pgmatrix.sh and schema-matrix.yml, fold its grammar delta into the base grammar in pgsql.ts (the base targets the oldest supported server, so the delta table's floor moves up), sweep search.sql for branches that only existed for it, and raise the min= floors in matrix_fixture.sql. Keep the removal in one commit so the range change reads as one decision.
The inventory
| Surface | File(s) | Changes when |
|---|---|---|
| Snapshot renderer and dictionary | internal/schemasnap/search.sql, sql/ | Catalog or render-function changes, new families |
| Version matrix | scripts/pgmatrix.sh, .github/workflows/schema-matrix.yml, internal/schemasnap/testdata/matrix_fixture.sql | Every new major, every dropped one |
| Editor grammar per major | web/src/lib/pgsql-versions.ts (deltas), pgsql.ts (base, oldest supported) | New keywords, functions, types; base only when the floor moves |
| Structural parser (completion scope, formatter) | web/public/treesitter/postgres.wasm.gz + README | When upstream regenerates from the new gram.y |
| Docs links | web/src/lib/pgdocs.ts | Only a renamed docs page; URLs are per-major already |
| Live catalog readers | Activity, Top queries (internal/db/sql) | Only when pg_stat views move |
| Client tools | System page install, backup and dump flows | pg_dump must cover the newest supported server |
| Dev and e2e containers | AGENTS.md, Makefile | When the new major becomes the daily default |
What deliberately does not track versions
The wire protocol (pgx, via make upgrade-go), Monaco itself, the action annotation format (server-agnostic by design, ACTIONSPEC.md), and the session and settings stores. None of these carry a PostgreSQL version anywhere, and nothing should be added to them that does.