Test a migration from a clean database
Create an empty database at the pinned engine/version, apply the complete migration chain, and assert tables, columns, types, constraints, indexes, grants, and seed/reference data. A fresh install catches missing or out-of-order migration dependencies.
Test an upgrade with representative existing data
- Build the previous schema revision and populate rows covering NULLs, boundaries, duplicates, and relationships.
- Apply the new migration with the same migration runner used in deployment.
- Verify transformed values, row counts, constraints, indexes, and application compatibility.
- Run an application smoke test against both the expected deployment phases when using an expand/contract rollout.
- Measure locks, runtime, disk use, and operational impact on representative volume.
Example expand-and-contract sequence
For a column rename, avoid dropping the old column before all application versions stop using it.
- Expand: add the new nullable column and deploy code that can read/write both formats.
- Backfill in controlled batches; assert every eligible row has matching values.
- Switch reads to the new column and observe production behavior.
- After compatibility is proven and old code is retired, enforce final constraints.
- Contract in a later migration by removing the old column with explicit approval.
The exact strategy depends on application architecture and engine locking behavior. Destructive changes require a tested restore/rollback plan; reverse DDL alone may not restore discarded data.
Migration failure checklist
- Does the migration runner stop on errors and report the failed revision?
- Can a rerun leave a consistent state, or is manual recovery required?
- Are DDL transaction semantics supported for each operation?
- Are existing rows preserved and application versions compatible?
- Has rollback or forward-fix behavior been rehearsed on a disposable copy?
Progress stays in this browser.