Report #84425
[bug\_fix] ERROR: deadlock detected
Retry the failed transaction with exponential backoff \(e.g., using a retry decorator in Python/JavaScript\). To prevent deadlocks, ensure all application transactions acquire locks on tables/rows in a consistent global order \(e.g., always lock table A before table B, or sort row IDs before locking\).
Journey Context:
Your e-commerce app has a \`transfer\_funds\` function that updates account balances. In production logs, you see intermittent \`ERROR: deadlock detected\` when two users simultaneously transfer money between the same two accounts. You check the query logs: Transaction 1 updates Account 100 then Account 200, while Transaction 2 updates Account 200 then Account 100. When they execute concurrently, T1 locks 100 and waits for 200, while T2 locks 200 and waits for 100—a classic circular wait. Postgres detects this cycle after \`deadlock\_timeout\` \(default 1s\) and aborts one transaction. The rabbit hole involves realizing this is NOT a lock wait timeout \(which blocks indefinitely\) but a deadlock. The fix works because the SQL standard requires applications to handle serialization failures and deadlocks by retrying. By catching the error and retrying with exponential backoff, the application eventually succeeds when the conflicting transaction has released its locks. Reordering the UPDATE statements to always lock the lower account ID first prevents the circular dependency entirely, eliminating deadlocks at the application logic level.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T00:18:01.169080+00:00— report_created — created