Skip to content

Implementation Plan: ANU-7 - Migrate Supabase Postgres data and verify local cutover

Scope

Inventory the current Supabase PostgreSQL source without recording secrets or row contents, export checksummed schema and data artifacts with the Supabase CLI, restore the application-owned database objects into the verified local PostgreSQL 17 and pgvector stack, and prove data and application parity. Switch only ignored machine-local CMS configuration after parity passes. Preserve the source unchanged and keep both the accepted local volume and a tested rollback to the prior Supabase URI.

Product Main inputs and dependencies

  • Product Main change: 2026-07-20-switch-to-local-postgres
  • Product Main source: docs/changes/2026-07-20-switch-to-local-postgres/index.md
  • Linear parent: ANU-5
  • Linear implementation child: ANU-7
  • Repository label: anuvax-cms
  • Required dependency: ANU-6, completed
  • Accepted local baseline: PostgreSQL 17.10, pgvector 0.8.2, pgAdmin 9.16, Node 22.5.1, and the persistent anuvax-cms-local Compose volumes

The normalized Linear scope, acceptance, documentation, and verification requirements are authoritative. Cross-repository or product-level decisions remain with Product Main.

Implementation approach

  1. Extend the guarded database tooling with redacted read-only inventory, checksum verification, reviewed application-schema selection, targeted parity, and rollback/cutover evidence. Keep every connection string in a named environment variable and every artifact below ignored .local-data/database/<run-id> storage.
  2. Pin and record the Supabase CLI version used for export. Run plan and refusal tests before any connection or restore execution.
  3. Inventory source PostgreSQL/extension versions, application schemas and roles, tables, constraints, sequences, Payload migrations, Mastra tables, RAG tables, and vector indexes. Record names and counts only.
  4. Export reviewed application schema and data with the Supabase CLI, checksum every dump, verify the checksums, and prove all artifacts are ignored and absent from Git.
  5. Create a fresh local migration target inside the accepted Postgres volume, install only required extensions, restore without blanket grants or unreviewed Supabase-managed schemas, and retain the prior local database for recovery.
  6. Run automated parity plus targeted SQL probes for representative keys, constraints, sequences, Payload migration state, workspace isolation, Mastra tables, RAG chunks, and deterministic vector-query behavior.
  7. Switch the ignored local CMS configuration to the restored database, then verify the containerized CMS, Payload admin/login boundary, workers, primary application paths, targeted tests, restart persistence, and rollback to the untouched Supabase URI without deleting the local volume.
  8. Update the implementation log, migration runbook, environment/service and testing documentation, then map exact redacted evidence into the completion report and Product Main synchronization section.

Expected tracked surfaces:

  • package.json and pnpm-lock.yaml
  • scripts/local-stack/database.ts
  • scripts/local-stack/*.sql and any focused migration helpers
  • tests/unit/local-stack.test.ts
  • docs/bootstrap/LocalDevelopmentStack.md
  • docs/core/TestingAndVerification.md
  • docs/state/EnvAndServices.md
  • docs/state/ScriptsAndCommands.md
  • docs/state/KnownGaps.md
  • this change folder, docs/changes/index.md, and mkdocs.yml

Documentation impact

  • Add the exact redacted inventory, export, checksum, restore, parity, cutover, failure-handling, restart, and rollback procedure to the local-stack runbook.
  • Update environment and command state after the local database becomes the accepted development default.
  • Record every executed command by purpose and result without copying database URIs, credentials, row contents, dump contents, or personal data.
  • Return preview-only URLs after planning, durable-doc updates, and final completion evidence. Product Main owns canonical publishing.

Verification and acceptance checks

Check Planned redacted evidence
Source inventory is complete and safe Inventory JSON with versions, object names, and aggregate counts only; source transaction is read-only
Exports are reproducible and private Supabase CLI version, schema/data dump results, SHA-256 manifest verification, ignore and Git-absence checks
Restore contains only reviewed objects Fresh loopback target, reviewed extension/schema list, restore log review, no blanket privilege changes
Structural and data parity Automated summary plus targeted counts, representative key existence hashes/counts, constraints, sequences, and migration state
Workspace, Mastra, RAG, and vector behavior Cross-workspace negative probes, Mastra relation checks, RAG chunk counts, deterministic vector query
CMS and worker behavior Compose health, Payload/admin and auth boundary probes, stack:verify, worker startup probes, primary flow tests
Persistence and rollback Restart/down-up persistence proof and a demonstrated source-URI rollback that leaves the local volume intact
Repository quality Targeted/full lint evidence, typecheck, integration tests, relevant Playwright projects, strict MkDocs, index validation

Skipped checks, limitations, and recovery state will be explicit. A dump or a successful restore alone is not acceptance.

Non-goals and rollback

Non-goals:

  • changing, pausing, deleting, or writing to the Supabase source
  • importing Supabase Auth, Storage, Realtime, Vault, or other managed schemas unless an application-owned dependency is explicitly demonstrated and reviewed
  • weakening privileges globally or preserving hosted ownership that the local application does not require
  • deleting the accepted local Postgres volume
  • production cutover or changes outside anuvax-cms

Rollback retains the untouched Supabase URI in ignored configuration/evidence, stops local application writes before switching, restores the prior URI to the ignored CMS configuration, and verifies a read-only application health path. The accepted local volume and restored database remain intact for diagnosis or forward recovery.