Scenario · Locks & Transactions
CREATE INDEX without CONCURRENTLY blocks writes
A sandboxed PostgreSQL incident — investigate with your own tools, submit a fix, and get deterministic Detect / Fix / Trap scoring.
L3 · 10–15 min · runs locally in Docker
Launch
Start this scenario
Boot it in a real PostgreSQL sandbox and investigate with psql, EXPLAIN and pg_stat_statements.
ride postgres start stage-02/05-create-index-without-concurrentlyPart of these paths
Show the postmortem & investigation hints spoilers
CREATE INDEX without CONCURRENTLY blocks writes Type: incident simulation · Topic: Locks & Transactions · Level: L3 · Duration: 10–15 min Launch: ride postgres start stage-02/05-create-index-without-concurrently POSTMORTEM (root cause · how it was found · the fix · lesson) Root cause: a migration ran a plain `CREATE INDEX` on a hot table. A non-concurrent index build takes a SHARE lock on the table for the entire build, which conflicts with the ROW EXCLUSIVE lock writes need — so every INSERT/UPDATE blocked until the build finished (here, an open transaction kept it blocking). How it was found: pg_stat_activity showed a session whose query was `CREATE INDEX ...`, holding a lock that pg_locks/pg_blocking_pids tied to the stalled writes. The fix: terminate the blocking build, then rebuild without blocking writes: CREATE INDEX CONCURRENTLY idx_orders_created_at_good ON orders (created_at); CONCURRENTLY builds the index without taking a blocking lock (it can't run inside a transaction block). Lesson: on a live table, always build indexes with CONCURRENTLY. A plain CREATE INDEX is a write outage. This is a release/migration discipline issue as much as a locking one. INVESTIGATION HINTS (the staged path to diagnose and fix) 1. Writes to orders started blocking during a release. Look at pg_stat_activity — a CREATE INDEX is running (in a transaction) and holding a lock that conflicts with writes. 2. A plain CREATE INDEX takes a SHARE lock that blocks all writes to the table for the whole build. On a hot table you must use CREATE INDEX CONCURRENTLY instead. 3. Terminate the blocking index build, then rebuild safely: CREATE INDEX CONCURRENTLY ... (note: CONCURRENTLY can't run inside a transaction block).