Database Migration Release Gate Workflow
Gate a release on backward-compatible migrations that can run before and after the code deploy without breaking either version.
Objective
Ensure database migrations are compatible with both the old and new application versions during a release.
Environment
- A migration tool with version tracking
- Staging data representative of production
- A rollback plan
Steps
1. Classify the migration
Determine whether the change is expand-only, contract, or destructive.
Expected state: The migration is classified and its phase plan is clear.
2. Deploy the expand phase
Add new columns or tables without removing anything the old code uses.
Expected state: Old and new code both run against the expanded schema.
3. Release the application
Deploy the new code that uses the new schema while the old schema still works.
Expected state: The deploy succeeds without schema errors.
4. Run the contract phase later
Remove the now-unused columns in a separate later release.
Expected state: The old schema is cleaned up only after the new code is stable.
Decision points
Rename a column directly?
- Add new plus backfill plus drop later
- Rename in place
Use expand-contract; in-place renames break the old version during rollout.
Run contract immediately?
- Wait for stability
- Same release
Wait until the new version is proven stable to avoid unrecoverable steps.
Expected outcome
Migrations are split into expand and contract phases so no release step breaks either application version.
Verification
Confirm the old code works after expand, the new code works after deploy, and contract runs only after the new version is stable.
Cleanup
Remove migration feature flags and document the contract phase.
Overview
Ensure database migrations are compatible with both the old and new application versions during a release.
This workflow is reusable across teams and environments; adapt the commands to your tooling while keeping the sequence and checkpoints intact.
Environment and prerequisites
- A migration tool with version tracking
- Staging data representative of production
- A rollback plan
Procedure
1. Classify the migration
Determine whether the change is expand-only, contract, or destructive.
Expected state: The migration is classified and its phase plan is clear.
2. Deploy the expand phase
Add new columns or tables without removing anything the old code uses.
Expected state: Old and new code both run against the expanded schema.
3. Release the application
Deploy the new code that uses the new schema while the old schema still works.
Expected state: The deploy succeeds without schema errors.
4. Run the contract phase later
Remove the now-unused columns in a separate later release.
Expected state: The old schema is cleaned up only after the new code is stable.
-- expand phase
ALTER TABLE orders ADD COLUMN note text;
-- contract phase (later release)
ALTER TABLE orders DROP COLUMN legacy_note;
Verification
Confirm the old code works after expand, the new code works after deploy, and contract runs only after the new version is stable.
Decision points
Rename a column directly?
- Add new plus backfill plus drop later
- Rename in place
Recommendation: Use expand-contract; in-place renames break the old version during rollout.
Run contract immediately?
- Wait for stability
- Same release
Recommendation: Wait until the new version is proven stable to avoid unrecoverable steps.
Common failures
- Destructive changes in the same release block rollback.
- Renaming in place breaks old pods during rollout.
- Contract too early removes data the old version still needs.