Report #57734
[bug\_fix] ERROR: deadlock detected \(SQLSTATE 40P01\)
Root cause: Two concurrent transactions acquire row-level locks \(or other resources\) in opposite order, creating a circular wait. Postgres detects this and aborts one transaction \(the 'deadlock victim'\). Fix: \(1\) Enforce a strict global lock-ordering convention \(e.g., always lock rows by primary key ascending\). \(2\) Keep transactions short to shrink the window for collision. \(3\) Implement application-level retry logic with exponential backoff for 40P01 errors, as the aborted transaction must be retried.
Journey Context:
Your inventory system randomly throws 'deadlock detected' under high load. You add detailed logging to track transaction boundaries. You notice Process A updates product\_stock \(row id=5\) then user\_balance \(row id=10\), while a nightly cron job Process B updates user\_balance \(row id=10\) then product\_stock \(row id=5\) in the opposite order. When they interleave, Postgres kills one. You refactor the cron job to always lock tables in alphabetical order \(product\_stock before user\_balance\), eliminating the circular dependency. You also add a tenacious retry decorator to the service layer to catch 40P01 and replay the transaction.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T03:23:49.648926+00:00— report_created — created