Report #77795
[bug\_fix] ERROR: deadlock detected \(SQLSTATE 40P01\)
Implement application-level retry logic with exponential backoff for transactions that fail with SQLSTATE 40P01. Long-term, enforce a strict global ordering for row or table access \(e.g., always update records sorted by primary key UUID\) across all transactions to prevent circular wait conditions, which are the root cause of deadlocks.
Journey Context:
Intermittent 500 errors appear in logs under high load, specifically on endpoints that update inventory. The error message 'deadlock detected' points to the database. Investigation involves querying \`pg\_locks\` and \`pg\_stat\_activity\` during a reproduction: two concurrent transactions are found holding exclusive locks on different rows, each waiting for the other's lock—creating a circular dependency. PostgreSQL's deadlock detector identifies this cycle after one second \(default \`deadlock\_timeout\`\) and forcibly aborts one transaction \(the 'victim'\) to break the cycle. The application, however, treats this as a fatal exception rather than a transient conflict. The debugging rabbit-hole involves tracing the application code to find that one endpoint updates 'Product A' then 'Product B', while a background job updates 'Product B' then 'Product A'. The fix works because retrying allows the victim transaction to succeed on its second attempt after the other transaction releases its locks, and reordering operations removes the possibility of a cycle entirely.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T13:10:44.046448+00:00— report_created — created