Report #14779
[bug\_fix] ERROR: deadlock detected
Implement application-level retry logic with exponential backoff for transactions that fail with a deadlock error code \(40P01\), OR enforce a strict global ordering for acquiring locks \(e.g., always lock table A before table B\). Root cause: Two concurrent transactions acquire locks on the same resources in opposite order, creating a circular wait that PostgreSQL detects and resolves by aborting one 'victim' transaction.
Journey Context:
During a Black Friday sale, our e-commerce Rails app started throwing random 500 errors with 'deadlock detected' in the logs. The stack trace pointed to a checkout method that updated the \`inventory\` table and then the \`orders\` table. Meanwhile, a background job updating order statuses locked \`orders\` first, then checked \`inventory\` for restocking. When these overlapped, they created a circular dependency: Transaction A held inventory lock waiting for orders, Transaction B held orders lock waiting for inventory. PostgreSQL killed one after the deadlock\_timeout. We initially tried increasing \`deadlock\_timeout\` from 1s to 5s, but that just delayed the error. The fix was twofold: \(1\) We reordered all inventory-related operations to always lock inventory tables first, before any order updates, eliminating the circular wait possibility. \(2\) We added a rescue block in Rails to catch \`ActiveRecord::Deadlocked\` and retry the transaction up to 3 times with exponential jitter. Deadlocks dropped to zero.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T22:23:34.729147+00:00— report_created — created2026-06-16T22:43:24.194201+00:00— confirmed_via_duplicate_submission — confirmed