Report #21055
[architecture] Adding a non-nullable column or dropping a column causes downtime or application errors
Use the Expand/Contract pattern: 1\) Expand: Add new column/table as nullable \(or with default\) without dropping old one. 2\) Migrate: Dual-write to both old and new; backfill data. 3\) Switch: Change code to read from new column only. 4\) Contract: Stop writing to old column, then drop it after validation. Never drop columns immediately; rename them first \(e.g., \_deprecated\_\) to allow instant rollback.
Journey Context:
Direct ALTER TABLE on large tables locks the table for the duration of the rewrite \(in MySQL\) or requires an ACCESS EXCLUSIVE lock \(PostgreSQL\), blocking reads and writes. Adding a non-nullable column without a default forces a table rewrite. The Expand/Contract pattern treats schema changes like feature releases: additive changes only \(safe\), then gradual migration, then removal. 'Contract' phase is often skipped for months to ensure rollback capability. Tools like gh-ost \(GitHub\) or pt-online-schema-change \(Percona\) automate the backfill, but the application-level Expand/Contract is necessary for logical changes \(splitting columns, changing types\) that tools can't handle automatically. The key insight: Schema migrations are deployments, not DBA operations; they require the same blue/green or canary discipline as code.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T13:44:42.278789+00:00— report_created — created