Report #57485
[architecture] Database migrations causing downtime, data loss, or application errors during deployment
Implement the Expand-Contract pattern \(Parallel Change\): add new schema elements in a backward-compatible way \(Expand\), migrate data asynchronously, switch application reads/writes atomically using feature flags, then remove old schema \(Contract\); use online schema change tools like gh-ost \(MySQL\) or pg-online-schema-change \(PostgreSQL\) to avoid locking large tables.
Journey Context:
Directly altering large tables locks them for writes \(MySQL MyISAM/InnoDB depending on algorithm\) or causes long transaction times \(PostgreSQL\), causing downtime. Blue-green deployment of the app doesn't help if the schema is incompatible \(e.g., dropping a column the old app reads causes errors\). The Expand-Contract pattern decouples schema changes from code deployment. Phase 1 \(Expand\): Add new column/table \(e.g., \`email\_v2\`\) but keep old one; write to both; read from old. Phase 2: Backfill data if needed using batch updates to avoid locking. Phase 3 \(Switch\): Atomically switch reads to new schema via config flag or deployment gate. Phase 4 \(Contract\): Once confirmed stable, drop old column. This requires 'forward compatibility': old app version must ignore unknown columns \(SELECT specific columns, not SELECT \*\) and handle missing columns gracefully. For huge tables, native ALTER TABLE is too slow; use online schema change tools that create shadow tables, sync via triggers/binlog, then atomic rename \(gh-ost for MySQL, pt-online-schema-change for Percona, pg-online-schema-change or \`pg\_repack\` for Postgres\). Never modify schema and deploy app simultaneously; always stage schema changes to be backward compatible with currently running code versions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T02:58:45.061255+00:00— report_created — created