Implementing Database Migrations

1. Choosing Migration Tools

ToolEcosystem
FlywayJVM, multi-DB, SQL-first
LiquibaseXML/YAML/SQL changelogs
AlembicPython / SQLAlchemy
Knex / PrismaNode.js
Rails Active RecordRuby
SqitchDependency-based, no ORM
AtlasDeclarative schema mgmt

2. Writing Forward Migrations

Example: Flyway SQL Migration

-- V20260315.1430__add_user_status.sql
ALTER TABLE users ADD COLUMN status TEXT;
UPDATE users SET status = 'active' WHERE status IS NULL;
ALTER TABLE users ALTER COLUMN status SET NOT NULL;
ALTER TABLE users ADD CONSTRAINT users_status_chk
  CHECK (status IN ('active','suspended','deleted'));
RuleDetail
Idempotent where possibleIF NOT EXISTS guards
Small, atomicOne logical change per file
Never edit shipped migrationAdd new one instead

3. Implementing Reversible Migrations

AspectDetail
Up + DownEach change has inverse
Data loss warningDROP TABLE down is destructive
Soft rollbackPrefer forward fix in production
Test down locallyVerify the inverse works

4. Managing Migration Versions

StorageDetail
schema_history tableTracks applied versions + checksum
Timestamp-based namesAvoid merge conflicts on numeric IDs
Lock during applyPrevent concurrent runs
Repair commandFix corrupted history (rare)

5. Running Migrations in CI/CD

StageAction
PRLint migration + apply on ephemeral DB
Pre-deployApply to prod before app rollout
Init container / Jobk8s pre-install hook
Lock + timeoutFail fast on conflicts
Logs + statusTrack in deployment pipeline

6. Handling Migration Failures

FailureResponse
Syntax errorWrap in transaction; auto-rollback
Timeout / lockRetry off-hours; use lock_timeout
Constraint violation on backfillFix data first, re-run
DDL outside tx (MySQL)Manual cleanup required

7. Implementing Zero-Downtime Migrations

PatternDetail
Expand / contractAdd new shape; migrate; remove old
Online DDLCONCURRENTLY / ALGORITHM=INPLACE
App toleranceRead both old & new during transition
Background backfillBatched UPDATE jobs
Feature flagToggle code paths to new schema

8. Coordinating Schema and Code Changes

Coordinated Release

  1. Deploy app supporting both old & new schemas
  2. Run schema migration (expand)
  3. Run data migration (backfill)
  4. Deploy app reading/writing new only
  5. Run schema migration (contract: drop old)

9. Testing Migrations in Lower Environments

EnvTest
DevApply against empty + seeded DB
CIApply against fresh image; run app tests
StagingApply against prod-snapshot; measure timing
CanaryOptional dark-launch with shadow traffic

10. Documenting Migration Procedures

DocDetail
Per-migration READMERisk, rollback, expected timing
RunbookHow to apply / abort / roll forward
Pre-flight checklistBackups, replication health, lock budget
Post-migration validationSmoke queries, metrics check