Down-migration templates for critical tables (op-infra Step 4 follow-up)
Context
Op-infra plan Step 4 originally listed "Create down migration templates for critical tables (persons, determinations, enrollments)" as sub-task 4. This was deferred when shipping the snapshot/rollback tooling because:
- Modern Postgres practice prefers forward-only migrations. A broken migration is fixed by writing a new forward migration that corrects the schema, not by running a
downSQL file. Maintaining a parallel down-migration tree doubles review burden and is rarely actually used in incidents. - The snapshot/rollback tool now covers the dev/CI rollback case — see
cargo xtask migrate rollback. For local "I broke it, restore my schema" the developer-ergonomics path is a snapshot, not a down migration. - Production rollback is
pg_basebackup+ WAL PITR (Step 3) — Postgres-level point-in-time recovery, not application-level down migrations.
Why this still might be worth doing
Some tables genuinely benefit from documented down migrations as a contract: tables with audit-chain semantics (FTI), tables backing signed JWS determinations, tables holding historical compliance data. For these, a documented "this is how you'd reverse this migration if you absolutely had to" lives next to the up migration as part of the table's spec.
This is a needs-spec issue rather than ready: the right answer might be (a) write down templates only for the audit-sensitive tables, (b) write a policy doc that says "no down migrations; here's the alternative", or (c) some hybrid.
Acceptance criteria
- ADR or design doc decides the project-wide stance (down templates / no / hybrid).
- If hybrid: identify which tables warrant down templates (FTI audit log, signed determinations, compliance data) and write them.
- If no: a policy page in
docs/modules/ROOT/pages/development/explaining the forward-only approach and how to roll back in dev (xtask migrate rollback) and prod (PITR).
Source
Op-infra plan Step 4, sub-task 4 deferred when the implementation MR landed.