Skip to content

Add an opt-in PostgreSQL 18 target to the verification rig - #2657

Merged
erikdarlingdata merged 1 commit into
devfrom
feat/rig-pg18-target
Aug 26, 2026
Merged

Add an opt-in PostgreSQL 18 target to the verification rig#2657
erikdarlingdata merged 1 commit into
devfrom
feat/rig-pg18-target

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Follow-on from #2653 and #2655, which were both found and verified by running two PostgreSQL majors at once.

Why

Version drift in the catalog views is silent from a single server. 17 gutted pg_stat_bgwriter (five
columns to pg_stat_checkpointer, buffers_backend deleted outright); 18 removed pg_stat_io's
op_bytes and replaced it with measured read_bytes / write_bytes / extend_bytes. In both cases a
collector that guards the difference correctly and a read that quietly returns NULL look identical from
one target.

The rig could not do this: PG_MAJOR replaces the target rather than adding one, so you can have 17 or 18,
never both.

What

docker compose --profile multiversion up -d    # adds a plain PostgreSQL 18 on 55418

Opt-in via a compose profile, so the default up -d stays the two-container rig it is today.

Registering both targets in one darling.json turns the difference into an observable — which is exactly
how the two issues above got verified:

  • the registry stamps postgres_major_version 17 and 18 side by side
  • pg_io_stats splits cleanly: 17's rows carry op_bytes and no read_bytes, 18's the reverse
  • get_pg_io_stats answers estimated_from_block_size for one and measured for the other

It also quantifies what reasoning gets wrong. 18's vectored reads mean one entry in reads can cover
several blocks, so the pre-18 reads × block_size estimate undercounts — measured on this rig at 10× to
16×
, not the few percent it sounds like in the abstract.

The one design choice worth stating

The 18 target is the plain image, not the extension build. PGDG extension packages do not track a new
major immediately, and pinning this service to them would make the whole rig fail to build on the day a
major ships — precisely when a newest-major target is most useful. It exercises the core catalog views,
which is where version drift lives; the extension-backed collectors stay on the 17 target.

Version drift is silent from one server. 17 gutted pg_stat_bgwriter and 18 removed
pg_stat_io's op_bytes, and in both cases a collector that guards the difference
correctly and a read that quietly returns NULL look identical unless two majors are
present at once. #2653 and #2655 were both found and verified that way, and the rig
could not do it -- PG_MAJOR replaces the target rather than adding one.

`docker compose --profile multiversion up -d` adds a plain PostgreSQL 18 on 55418,
alongside the existing 17. Opt-in so the default stays a two-container rig.

Deliberately the plain image, not the extension build: the PGDG extension packages
do not track a new major immediately, so pinning to them would make the whole rig
fail to build on the day a major ships -- exactly when this target is most useful.
It exercises the core catalog views, which is where version drift lives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 26, 2026

Copy link
Copy Markdown

Reviewed. This is a self-contained addition to the local dev verification rig (docker-compose.yml + README) — no T-SQL, no Lite/Darling application code touched, so the parity concerns and T-SQL style rules don't apply here.

Checked:

  • New target18 service is profile-gated (multiversion), so the default up -d two-container rig is unchanged — matches the PR's stated intent.
  • Port 55418 doesn't collide with the existing 55432 (target) / 55441 (store) mappings.
  • Deliberately using the plain postgres:18 image rather than the extension-build Dockerfile is explained and consistent with the existing store service, which also uses a bare postgres:17 image.
  • The README's claims about pg_stat_bgwriter/pg_stat_io drift and get_pg_io_stats/estimated_from_block_size line up with what's actually implemented in Darling/PerformanceMonitor.Darling.Storage/DarlingPgIoReader.cs and covered by Darling.Tests/Pg18IoBytesTests.cs, so the docs aren't describing aspirational behavior.
  • Hardcoded targetpw password follows the same convention already used by the target and store services in this file — not a new risk introduced here.
  • No CI workflow references this rig, so this is purely an opt-in local tool; no pipeline impact.

No correctness, security, or parity issues found. Nothing blocking.

@erikdarlingdata
erikdarlingdata merged commit abeb9b8 into dev Aug 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant