Handling DB Migrations in CI/CD Safely
Introduction
Database migrations are the highest-risk part of deployment because they can permanently alter state. Safe automation requires backward-compatible changes, validation, and explicit rollout sequencing.
Adopt the Expand and Contract Pattern
The safest strategy is to expand the schema first, deploy application changes, then contract old fields later.
Workflow:
- Add new columns or tables without removing old ones.
- Deploy application code that writes to both old and new fields.
- Backfill data.
- Remove old fields after validating usage.
Migration Automation in CI/CD
Migrations should be executed as part of deployment, not manually. For EF Core, a migration can be applied via a dedicated migration job.
1
2
3
4
using Microsoft.EntityFrameworkCore;
await using var db = new OrdersDbContext();
await db.Database.MigrateAsync();
Run this in a migration step with strong RBAC and a short timeout to avoid long-running locks.
Pre-Deployment Validation
Use dry-run checks before applying migrations:
- Validate migration scripts in a staging environment.
- Detect destructive operations and require explicit approval.
- Confirm that the migration is backward compatible with the currently running code.
Data Backfills
Large backfills should run asynchronously. Use background jobs with throttling and checkpoints to avoid long locks.
Rollback Strategy
Schema rollbacks are harder than application rollbacks. Ensure old code can run against the new schema until full validation is done. Avoid dropping columns until the system is stable.
Summary
Safe database migrations depend on backward compatibility, automation, and deliberate sequencing. Treat migrations as first-class deployment steps, and apply them with the same rigor as application releases.