Report #67830
[architecture] Zero-downtime schema changes \(renaming columns, changing types\) in high-traffic PostgreSQL
Implement the expand-contract pattern: 1\) Add new column \(expand\), 2\) Dual-write to old and new in application code, 3\) Backfill existing data in idempotent batches, 4\) Switch reads to new column, 5\) Remove old column \(contract\). Never use \`ALTER TABLE\` destructive operations on live tables.
Journey Context:
Direct DDL operations like \`ALTER TABLE RENAME COLUMN\` or \`DROP COLUMN\` take exclusive locks that block reads and writes, potentially for minutes on large tables. The expand-contract pattern treats schema changes like feature flag rollouts. The critical step is the backfill: use \`UPDATE ... WHERE id BETWEEN $1 AND $2\` in small batches \(e.g., 1000 rows\) with throttling \(e.g., \`pg\_sleep\(0.1\)\`\) between batches to avoid locking contention. During the dual-write phase, ensure both columns are updated atomically within the same transaction to maintain consistency. This pattern works for renames, type changes \(add new column with cast\), and even table splits \(write to both tables\). Tools like \`gh-ost\` or \`pt-online-schema-change\` automate this for MySQL; for PostgreSQL, use \`pg\_repack\` or manual application-level expansion.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T20:19:56.993835+00:00— report_created — created