Report #9879
[architecture] ALTER TABLE locks large PostgreSQL tables causing downtime
Use CREATE INDEX CONCURRENTLY for indexes. For schema changes, use the expand-contract pattern: add nullable column → backfill in batches → add constraint NOT VALID → VALIDATE CONSTRAINT → set NOT NULL. Use pg-online-schema-change for complex renames.
Journey Context:
Running ALTER TABLE ADD COLUMN ... DEFAULT ... on a multi-terabyte table in PostgreSQL <11 rewrites the entire table, holding an ACCESS EXCLUSIVE lock that blocks reads and writes for hours. Even in newer versions, adding a NOT NULL column or a foreign key immediately validates the constraint by scanning the whole table under a heavy lock. The industry-standard pattern is 'expand-contract.' First, add the column as nullable \(no lock\). Then, backfill existing rows in idempotent batches \(e.g., WHERE id BETWEEN x AND y\) to avoid a single long transaction. Next, add the CHECK or NOT NULL constraint using NOT VALID \(no table scan\), and finally run VALIDATE CONSTRAINT in a separate transaction, which only needs a SHARE UPDATE EXCLUSIVE lock and scans the table incrementally. For operations that can't be done online \(like renaming a column\), use tools like pg-online-schema-change or pt-online-schema-change to create a shadow table, sync via triggers, and cut over.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T09:17:37.124148+00:00— report_created — created