Software Engineering

8 min read · Oct 2026

Safer Database Migrations: A Plan for Change and Recovery

A schema change affects applications, reports, and background jobs. Explore a practical expand, migrate, and contract workflow that checks compatibility, moves data deliberately, and defines recovery limits before deployment, without confusing lower migration risk with a promise that downtime cannot occur.

Safer Database Migrations: A Plan for Change and Recovery

Renaming a field looks simple until an old report or background worker reads it. Migration coordinates application versions, data and ongoing work. Separate steps reduce risk, but data volume, change type, and database behavior still determine the possibility of downtime.

01-Identify what remains active during the transition

Inventory applications, reports, and jobs that read or write the data. Record which versions may coexist, expected workload, and who decides whether to continue or stop.

PostgreSQL documents different lock requirements for ALTER TABLE operations, with many forms requiring a strong lock. Rehearse against similarly sized data and observe lock waits and query latency. Success on an empty table does not establish production behavior.

02-Expand while keeping the old shape usable

Parallel Change stages incompatible changes through expansion, migration, and removal of the old interface. In a hypothetical approvals system, we want to replace approved with approvalState.

Add the new field while retaining the old one, then deploy code that understands both. Define the source of truth and how new writes reach both representations. Do not assume separate writes succeed together; handle divergence or use a suitable transaction where possible.

03-Move data with verifiable rules

Prisma's guide illustrates moving values into a new field before removing the old field. For our approvals example, document how true becomes approved and false becomes pending, and isolate exceptions for review.

Use resumable batches for large datasets; record progress and monitor workload. Prevent batches from overwriting newer updates. Validate meaning, not just row counts. Decide how a failed batch can run again and how records missed by the transformation will be detected.

04-Switch reads before removing dependencies

Direct reads to the new field using a switch that can be reversed. Compare important journeys, including pending requests and approval reports. Check exports and scheduled jobs; a working homepage does not establish migration completeness.

Keep the previous application version usable throughout the agreed rollback window. If new states cannot be represented in the old field, defer them or define an acceptable reverse mapping before activation. Record potential loss of meaning for the decision maker.

05-Contract after proving the old path is unused

Contract removes old fields and compatibility paths once no active application version or scheduled job depends on them. Treat it as a separate deployment with acceptance conditions, with deliberate timing.

Test restoration and identify the last safe rollback point. Old code alone cannot recover deleted data, and restoring a backup requires a plan for newer writes. A forward repair may be more appropriate after that boundary.

Your next step

A migration plan specifies sequence, evidence for each stage, and who stops it when results differ. Base recovery on the data state, rather than a button that redeploys earlier code.

Safer Database Migrations: A Plan for Change and Recovery | Nawah Software