Report #100097
[bug\_fix] ERROR: 40P01: deadlock detected
Acquire locks in a consistent order across the whole application \(for example, ORDER BY id ASC\), keep transactions as short as possible, and add application-level retry with exponential backoff for transactions that abort with a deadlock.
Journey Context:
An e-commerce checkout flow kept logging ERROR: 40P01: deadlock detected in PostgreSQL 15. Two concurrent transfers updated the same two account rows in opposite order: request A updated from\_account first, then to\_account; request B updated to\_account first, then from\_account. Each UPDATE acquired a row-level exclusive lock, and when the second row was needed by the other transaction, PostgreSQL's deadlock detector killed one of them. The DETAIL line in the log showed a circular wait graph between the two processes. The fix was to sort account IDs in memory before issuing UPDATEs so every code path always locks the smaller ID first. We also wrapped the transfer block in a retry loop that catches DeadlockDetected, rolls back, waits a random jittered interval, and replays the transaction. Consistent lock ordering removes the cycle; the retry handles any rare residual races.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-01T04:38:55.800028+00:00— report_created — created