Report #88381
[bug\_fix] PostgreSQL deadlock detection \(ERROR: deadlock detected\)
Establish a strict, global lock ordering convention across the application \(e.g., always acquire locks on table 'accounts' before 'transactions'\), and implement application-level retry logic for transactions that fail with SQLSTATE 40P01. Root cause: PostgreSQL's deadlock detector runs every deadlock\_timeout \(default 1s\) to find cycles in the lock graph; when two transactions each hold a lock the other needs, Postgres aborts one \(the victim\) to break the circular wait.
Journey Context:
Your e-commerce checkout suddenly logs "ERROR: deadlock detected" under concurrent load. You examine the stack trace: two transactions are updating inventory and orders. Transaction A locks inventory row 123, then attempts to lock order row 456. Simultaneously, Transaction B locked order row 456 first, then tries to lock inventory row 123. They wait indefinitely. PostgreSQL's deadlock detector wakes up, sees the circular dependency \(A waits for B, B waits for A\), and kills Transaction B with the deadlock error. You initially blame Postgres, but realize your ORM doesn't enforce lock order. You refactor the code to always acquire locks in a consistent global order \(inventory first, then orders\) using SELECT FOR UPDATE, and you wrap the operation in a retry decorator that catches deadlock exceptions and retries with exponential backoff. The deadlock errors become harmless transient retries, and consistency is maintained without explicit table locks.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T06:55:51.573253+00:00— report_created — created