Porting · porting/2026-05-05-database-readiness-gate.md Docs Home

Database Readiness Gate

Date: 2026-05-05

Objective

Make the database state explicit before the Hetzner stack is treated as deployable.

The previous local runtime proof showed that the services can start. This gate adds a database-specific proof:

  • Studio API migrations exist and have been applied locally.
  • Zweistein has a synchronized schema locally, but no migration source was found in the imported snapshot.
  • Hetzner needs an explicit Studio migration step before application startup is considered ready.

What Was Added

  • scripts/database-gate.mjs Local and Hetzner database helper for migration/table-count checks and Studio API migration execution.
  • package.json scripts:
    • db:local:check
    • hetzner:db:plan
    • hetzner:db:commands
    • hetzner:db:studio:migrate
    • hetzner:db:check

Local Evidence

Run:

npm run db:local:check

Latest result:

  • Studio API migration source files: 84.
  • Studio API applied migrations: 84.
  • Studio API public tables: 37.
  • Studio API latest migration: AddExternalUsersToFlowProtection1758128437372.
  • Zweistein public tables: 39.
  • Zweistein src/dataSource.ts: not present.
  • Zweistein src/migrations: not present.
  • Zweistein migration files: 0.
  • Zweistein primary TypeORM connection has synchronize:true.

No database rows or secret values are printed.

Hetzner Database Sequence

Run this after real env values exist and after the relevant images are built:

npm run hetzner:db:plan
npm run hetzner:db:commands
npm run hetzner:db:studio:migrate
npm run hetzner:db:check

The helper runs the Studio API migration command through the Compose service:

docker compose --env-file configs/hetzner/frontend-build.env -f docker-compose.hetzner.yml run --rm --no-deps studio-api npm run migration:run

Then it checks migration and table counts through Postgres without printing table rows.

Zweistein Boundary

The imported Zweistein server currently has package scripts for migrations, but the expected TypeORM data source and migration files are not present:

  • legacy-src/zweistein/server/src/dataSource.ts: missing.
  • legacy-src/zweistein/server/src/migrations: missing.

The primary Zweistein DB connection currently uses:

synchronize: true

That is acceptable as a local preservation proof, because it creates the legacy schema from the entities. It is not a production-grade Hetzner database strategy.

Before a production cutover, one of these must happen:

  • recover the original Zweistein migration history;
  • create a baseline migration from the synchronized schema;
  • create a fresh migration plan for the rebuilt service.

Local Verification Evidence

  • node --check scripts/database-gate.mjs passed.
  • npm run db:local:check passed.
  • npm run hetzner:db:plan prints the DB sequence and current source facts.
  • npm run hetzner:db:commands prints the exact Compose/Postgres commands.
  • npm run hetzner:db:check fails locally as expected because it is guarded for native Linux x64/amd64.

Current Boundary

The DB gate is ready as a helper, but it has not been executed on a real Hetzner server yet.