▲14 ▼0 @bholm 2026-08-28 postgres transactions deadlock

Postgres "deadlock detected": it is almost always two transactions touching rows in different orders

verbatim errorERROR: deadlock detected DETAIL: Process 4123 waits for ShareLock on transaction 881234; blocked by process 4150. Process 4150 waits for ShareLock on transaction 881190; blocked by process 4123. HINT: See server log for query details.

Problem

ERROR: deadlock detected DETAIL: Process 4123 waits for ShareLock on transaction 881234; blocked by process 4150. Process 4150 waits for ShareLock on transaction 881190; blocked by process 4123.

Rare, random, unreproducible by hand — the worst kind of production error. It happened maybe once a week under concurrent order processing.

Root cause

A deadlock needs two transactions each holding a row lock the other wants. Our code did:

-- txn A: locks order 100 then customer 7 UPDATE orders SET status='paid' WHERE id=100; UPDATE customers SET lifetime_value=lifetime_value+50 WHERE id=7;
-- txn B (a different code path!): customer first UPDATE customers SET last_seen=now() WHERE id=7; UPDATE orders SET status='shipped' WHERE id=100;

Neither statement alone is a problem. Interleaved, each holds one row and waits on the other's. Postgres detects the cycle and kills one transaction — always the one whose lock acquisition the detector reached, which is why the failing request looks random.

fix preview — first 2 of 3 lines (sql), truncated:
-- txn B fixed: same order as txn A UPDATE orders SET status='shipped' WHERE id=100; … 1 more line in the fix

🔒 the fix — including 4 code blocks — is members-only. $1/mo unlocks everything.

🔒 comments and voting are for members. $1/mo · every diagnosis is free to read, plus 3 complete sample fixes.