feat(template): pre-bake initialized PGDATA to skip first-boot initdb#8
Merged
Conversation
A fresh Postgres primary ran `initdb` plus the full `CREATE EXTENSION` suite in the guest before accepting connections — ~1-2s+ squarely on the cold-boot critical path. Bake an already-initialized cluster (initdb + extensions) into the rootfs at image-build time and copy it onto the fresh data volume on first boot instead. - `beyond-pg build-template <dir>` (new subcommand): runs the canonical `pg::initdb` flag set into <dir>/main, starts a build-time postgres with the same filtered `shared_preload_libraries`, and creates the same REQUIRED+OPTIONAL extension set the supervisor would (reusing its lists + `extension_installed` filter) — single source, so the baked cluster can't drift from what the runtime expects. Points at the shipped pg_hba (local peer) so the build-time psql authenticates without a password. - `maybe_initdb` materializes the template when present (atomic staging + rename, pg_wal symlink repointed to the runtime waldir, targeted fsync), else falls back to runtime initdb. PG_VERSION only appears once a complete, correct PGDATA is published, so the skip-on-PG_VERSION check stays safe and an interrupted materialize is simply redone next boot. - Per-instance state (superuser/replicator passwords, roles) stays OUT of the template; `post_start` applies it every boot, so no shared build-time secret is exposed and `CREATE EXTENSION IF NOT EXISTS` becomes a no-op on first boot. Verified: chroot build-template produces a 40M template (initdb + beyond_queue, pg_cron, pg_stat_statements, pg_trgm, hypopg, pg_repack) and a clean delta; unit tests cover materialize copy/symlink/idempotency/leftover-staging recovery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A fresh Postgres primary ran
initdb+ the fullCREATE EXTENSIONsuite in the guest before accepting connections — ~1-2s+ on the cold-boot critical path. This bakes an already-initialized cluster into the rootfs at image-build time and copies it onto the fresh data volume on first boot instead.What
beyond-pg build-template <dir>(new subcommand) — runs the canonicalpg::initdbflag set, starts a build-time postgres with the runtime's filteredshared_preload_libraries, and creates the sameREQUIRED+OPTIONALextension set the supervisor would (reusing its lists +extension_installedfilter, so the baked cluster can't drift). Run by a newpacker/scripts/10-pgdata-template.shprovisioner in the image build.maybe_initdbmaterializes the template when present (atomic staging + rename,pg_walsymlink repointed, targeted fsync), else falls back to runtimeinitdb.post_startapplies it every boot, so no shared secret is exposed andCREATE EXTENSION IF NOT EXISTSbecomes a no-op on first boot.Verification
build-templateproduces a 40M template (initdb + beyond_queue, pg_cron, pg_stat_statements, pg_trgm, hypopg, pg_repack) + clean delta (334MB).🤖 Generated with Claude Code