Report #14948
[architecture] Performing zero-downtime schema changes on large PostgreSQL tables without locking
For adding nullable columns or non-volatile defaults in PostgreSQL 11\+, use ALTER TABLE ... ADD COLUMN ... DEFAULT ... \(non-blocking\). For adding indexes, use CREATE INDEX CONCURRENTLY. For complex changes \(renaming columns, changing types\), use pg-online-schema-change \(Ruby\) or pg-osc which creates a shadow table, syncs via triggers, then swaps tables using ACCESS EXCLUSIVE lock only during the final rename. Never use standard ALTER TABLE on tables >1GB during peak traffic.
Journey Context:
Standard ALTER TABLE takes ACCESS EXCLUSIVE locks, blocking reads and writes for seconds to minutes on large tables. Adding a column with a volatile default \(like now\(\)\) rewrites the table in old PG versions; in PG 11\+ it's fast but still requires a full table scan to populate defaults. CREATE INDEX without CONCURRENTLY locks writes. The shadow table approach \(pt-online-schema-change for MySQL, pg-online-schema-change for PG\) is the only safe way to change column types or add non-nullable columns without downtime, but it doubles storage and adds replication lag during the copy phase. The trigger-based sync has overhead; use during low traffic.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T22:48:26.028747+00:00— report_created — created