Databases
Schema migrations: multiple-choice review
Six questions that cut across the whole unit. Each one mirrors a decision you make while shipping a schema change to a live database under traffic — not a definition to recite, but a failure mode to defend against.
Confirm you can connect lock behaviour, safe-DDL rewrites, the expand-contract phases, backfill blast radius, and deploy ordering — the synthesis the seven lessons built toward.
On PG 16 a deploy runs the statement below and it completes in 8 ms, yet the users table returns 503s for 70 seconds. A 60-second analytics SELECT was already in flight on users when the ALTER fired. What actually froze the table? ```sql ALTER TABLE users ADD COLUMN status TEXT DEFAULT 'active'; ```
The same instant ALTER from question 1 keeps timing out behind long queries. Which single change turns 'migration freezes the database' into 'migration logs an error and retries'?
You must add a FOREIGN KEY to a 100M-row orders table without blocking writes. Which approach is production-safe?
A rolling deploy is renaming users.username to users.handle. To keep both the old and new app versions working at every moment, which step ordering is correct?
A backfill ships as one statement on a 100M-row table. On a primary + 2 replicas, what is the first thing that breaks and what is the durable fix? ```sql UPDATE users SET handle = username WHERE handle IS NULL; ```
Three Kubernetes replicas boot at once and each runs migrate up on startup. One succeeds; two crash with duplicate-object errors. What was missing, and what is the cleaner production pattern?
The unit’s through-line is one defensive checklist for every schema change. Locks: most DDL needs ACCESS EXCLUSIVE and the FIFO queue turns one slow query into a table freeze — SET lock_timeout so a failed attempt aborts and retries. Rewrites: a constant default is instant since PG 11, volatile defaults still rewrite. Constraints and indexes: NOT VALID + VALIDATE and CREATE INDEX CONCURRENTLY take SHARE UPDATE EXCLUSIVE and leave DML running. Breaking changes: expand-contract keeps old and new code compatible at every moment, never a single-step rename. Backfills: batch to bound the WAL flood and replica lag. Runners: serialise with an advisory lock and gate a pre-deploy job before the rollout. Every answer resolves back to the same invariant — the schema must stay compatible with both code versions, at every moment, without freezing the table.