Skip to content

feat(cli): cache the shadow database baseline as a PGDATA snapshot (CLI-2191) - #6184

Open
avallete wants to merge 105 commits into
developfrom
avallete/shadow-db-perf-6ad622
Open

feat(cli): cache the shadow database baseline as a PGDATA snapshot (CLI-2191)#6184
avallete wants to merge 105 commits into
developfrom
avallete/shadow-db-perf-6ad622

Conversation

@avallete

@avallete avallete commented Aug 13, 2026

Copy link
Copy Markdown
Member

db diff / db pull / declarative sync rebuild the shadow's platform baseline (initdb + init SQL + the PG15+ one-shot realtime/storage/auth jobs, ~15s) on every run, before user migrations even start. This PR makes that a once-per-config cost. Measured on a default-services PG17 project: ~3.3s warm provision vs ~15.5s cold.

The cache is opt-in for soak (SUPABASE_SHADOW_CACHE=1 / true; unset is off). After soak it can flip to default-on.

What changed

  1. Readiness gate. The shadow's docker healthcheck cannot report before t+10s (10s interval, no start_period), so legacyWaitForShadowReady polls container state plus a short authenticated connect (500ms spacing, 2s connect timeout). Same timeout budget, error shape, and log dump. The healthcheck config and the long-running db container's wait are untouched.
  2. exec'd postgres entrypoint. PID 1 was sh, which swallowed SIGTERM, so every docker stop burned the 10s grace period. All three entrypoint variants now exec; stops take ~1s (also benefits supabase stop).
  3. Baseline snapshot cache (off unless SUPABASE_SHADOW_CACHE is set). When enabled, the cold path stops the shadow after the platform baseline and streams PGDATA to ~/.supabase/cache/shadow-baseline/shadow-baseline-<key>.tar (~90MB; SUPABASE_HOME overrides the root). A matching later run unpacks that tar into a fresh container before docker start — initdb and the baseline are skipped, migrations apply directly.

Cache contract

  • Pristine by construction. Every run gets a new container restored from the baseline's exact bytes. No reset protocol, metadata, lock file, or kept container — concurrency is the atomic rename.
  • Artifact is a tar stream through docker cp -. The directory form of docker cp resets ownership to root and Postgres refuses the data dir.
  • Shared across worktrees with the same settings. Retention is LRU keep-3 + 2-day mtime TTL; the current key is never evicted; abandoned .partial files older than 5 minutes are swept. Warm hits refresh mtime.
  • The key hashes every input baked into the cluster (images including enabled-service job tags, jwtSecret, rootKey, db password/settings, jwtExpiry, auto_expose, roles.sql, vault names+values, shadowPort, major_version, JWKS when realtime is on PG≥15, effective webhooks/pg_net policy).
  • OrioleDB and PG ≤ 14 are cache-ineligible. sync --no-cache bypasses the cache for that invocation.
  • Cold export drops --rm (Docker destroys an AutoRemove container on docker stop). Release still removes every shadow; a SIGKILLed CLI leaves at most one stopped project-labeled container, swept by supabase stop.
  • A cache miss or anomaly never fails the run, except when the shadow does not come back after a cold export. Warm anomalies delete the suspect tar and cold-provision; a failed export warns and continues uncached.

Still uncached: db diff --use-pgadmin, db pull --declarative's raw shadow, migration squash.

avallete and others added 30 commits August 6, 2026 09:04
…lta-next

# Conflicts:
#	apps/cli-go/cmd/db.go
#	apps/cli/docs/go-cli-porting-status.md
#	apps/cli/src/legacy/commands/db/diff/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/diff/diff.handler.ts
#	apps/cli/src/legacy/commands/db/diff/diff.integration.test.ts
#	apps/cli/src/legacy/commands/db/diff/diff.layers.ts
#	apps/cli/src/legacy/commands/db/pull/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/pull/pull.handler.ts
#	apps/cli/src/legacy/commands/db/pull/pull.integration.test.ts
#	apps/cli/src/legacy/commands/db/pull/pull.layers.ts
#	apps/cli/src/legacy/commands/db/push/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/reset/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/schema/declarative/declarative.orchestrate.integration.test.ts
#	apps/cli/src/legacy/commands/db/schema/declarative/declarative.orchestrate.ts
#	apps/cli/src/legacy/commands/db/schema/declarative/generate/generate.handler.ts
#	apps/cli/src/legacy/commands/db/schema/declarative/generate/generate.integration.test.ts
#	apps/cli/src/legacy/commands/db/schema/declarative/sync/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/schema/declarative/sync/sync.handler.ts
#	apps/cli/src/legacy/commands/db/schema/declarative/sync/sync.integration.test.ts
#	apps/cli/src/legacy/commands/db/shared/legacy-pgdelta.seam.layer.ts
#	apps/cli/src/legacy/commands/db/shared/legacy-pgdelta.seam.service.ts
#	apps/cli/src/legacy/shared/db-bootstrap/db-setup.ts
#	apps/cli/src/legacy/shared/legacy-db-connection.sql-pg.layer.ts
#	apps/cli/src/legacy/shared/legacy-http-errors.ts
#	apps/cli/src/legacy/shared/legacy-migration-apply.ts
#	apps/cli/src/legacy/shared/legacy-migration-apply.unit.test.ts
#	apps/cli/src/legacy/shared/legacy-pgdelta.cache.ts
#	packages/api/src/effect.ts
#	packages/api/src/internal/client.ts
#	packages/api/src/internal/client.unit.test.ts
…lta-next

# Conflicts:
#	apps/cli/src/legacy/commands/db/diff/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/diff/diff.handler.ts
#	apps/cli/src/legacy/commands/db/diff/diff.integration.test.ts
#	apps/cli/src/legacy/commands/db/pull/SIDE_EFFECTS.md
#	apps/cli/src/legacy/commands/db/shared/legacy-shadow-source.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9baed89bbc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts Outdated
The export now writes data/SUPABASE_BASELINE into the stopped shadow's
PGDATA right before the outbound docker cp, and warm-hit validation
requires it alongside data/PG_VERSION — a valid bare-cluster tar is
discarded as suspect instead of restoring into baselinePresent: true
and skipping setup. Only snapshotBaseline stamps, strictly after the
platform baseline, so a snapshot taken too early can never carry the
marker (regression guard). Uppercase name keeps the entry at the front
of docker cp's sorted tar so warm validations stay a first-blocks read.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4d494f4d96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/pgdata-snapshot.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts Outdated
…tants

The baseline marker's content is now the snapshot's own cache key and
warm validation verifies it, so a valid snapshot copied over another
key's filename is discarded (wrong-key verdict, distinct from a missing
marker) instead of restoring a mismatched baseline. The baseline digest
(renamed baseline_embedded_digest) now also hashes the Realtime seed
constants persisted by the one-shot job (tenant id, encryption key,
db user/name/port), so editing them without an image bump invalidates
stale tars.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b382f94904

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-database.ts
…cli-pr-conflicts-529506

# Conflicts:
#	apps/cli/src/legacy/shared/db-bootstrap/shadow-database.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9134f2e9f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
Docker-aware gate (describeDockerLive), ephemeral shadow port instead
of a fixed one, best-effort network removal in the scope finalizer, and
scoped SUPABASE_HOME/SUPABASE_SHADOW_CACHE overrides restored on every
outcome.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ca12af032

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
One runSupabaseLive golden path: init + minimal start, then db diff
--local --use-pg-delta twice against the same SUPABASE_HOME — the cold
run must export the tar (shadow-debug: baseline-export), the warm run
must restore it (baseline-restore, refreshed mtime, identical stdout).
Replaces the in-process legacyAcquireShadowDatabase calls, which could
stay green while the command wiring or env propagation broke; mechanics
coverage lives in the integration suite. Shadow port comes from
SUPABASE_DB_SHADOW_PORT with a bounded retry on bind conflicts — true
reservation is impossible since Docker must bind the port itself.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ba00ac249

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.live.test.ts Outdated
…n's pid

Eight candidates from a pid-seeded base in the IANA dynamic range
replace the fixed 54987/54988 pair, so independently concurrent runs
start from different bases and an occupied port costs one retry step.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d277539bb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts

@avallete avallete left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have SUPABASE_SHADOW_CACHE false by default.

So we can have a soaking / testing / opt-in period before releasing to all consumers.

Comment thread apps/cli/tests/helpers/legacy-mocks.ts
Comment thread apps/cli/tests/helpers/legacy-mocks.ts
Comment thread docs/roadmap/pg-delta-next-follow-ups.md Outdated
Comment thread apps/cli/src/legacy/shared/legacy-pgdelta.cache.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-pgdelta.cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/pgdata-snapshot.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/health-check.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/health-check.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/container-lifecycle.ts Outdated
Gate SUPABASE_SHADOW_CACHE through the viper helper, tighten tar
retention, drop the one-off debug channel, and reuse existing helpers.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7fd00b925a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/container-lifecycle.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/pgdata-snapshot.ts
The platform image still installs pgjwt, so RESTRICT drop of pgcrypto fails during CLI-owned shadow prep.
…erge-conflicts-848c2e

# Conflicts:
#	apps/cli/src/legacy/commands/db/shared/legacy-pgdelta-next-shadow.layer.ts
#	apps/cli/src/legacy/commands/db/shared/legacy-pgdelta-next-shadow.layer.unit.test.ts
Comment thread apps/cli/docs/go-cli-divergences.md Outdated
Comment thread apps/cli/src/legacy/commands/db/diff/diff.handler.ts Outdated
Comment thread apps/cli/src/legacy/commands/db/diff/diff.handler.ts Outdated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb21b82611

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/docs/go-cli-divergences.md Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-database.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/health-check.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
The next engine ignores schema_paths when building its migrations baseline, so the declared-schema drift diffed to nothing. Also fix the invalid 'analytics' exclude (logflare).

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c8ac90d5e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts Outdated
Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-database.ts Outdated
Comment thread apps/cli/src/legacy/shared/legacy-pgdelta.paths.ts
avallete and others added 2 commits August 24, 2026 14:04
- Revalidate roles.sql before publishing a cold baseline tar; a mid-provision edit skips the export instead of publishing under a stale key.
- Share one JWKS memo across provisionPlan's two shadows so their snapshot keys hash identical bytes.
- Scope legacyWaitForShadowReady's lastFailure per evaluation (Effect.suspend).
- Narrow the platform-error reason with Predicate.isTagged.
- Relocate the shadow-cache/session-semantics notes from the frozen go-cli-divergences.md into the SIDE_EFFECTS.md files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…omments

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e31bb57d1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/shared/db-bootstrap/shadow-cache.ts
Comment thread apps/cli/src/legacy/shared/db-bootstrap/container-lifecycle.ts Outdated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

2 participants