Report #13477
[bug\_fix] PostgreSQL deadlock detected \(SQLSTATE 40P01\)
Enforce a strict global ordering of row updates \(e.g., always ORDER BY id ASC\) and wrap the operation in an application-level retry loop with exponential backoff; root cause is concurrent transactions acquiring row locks in opposite orders, creating a circular wait-for graph.
Journey Context:
A high-throughput inventory service using Java Spring Boot intermittently throws "ERROR: deadlock detected" during concurrent order processing. The stack trace points to an UPDATE inventory SET quantity = quantity - ? WHERE product\_id = ?. Analyzing the deadlock logs via log\_min\_duration\_statement and log\_line\_prefix reveals two concurrent sessions: Session A holds a lock on product\_id=1 and wants product\_id=2; Session B holds product\_id=2 and wants product\_id=1. The application code has two different paths: the checkout API sorts by cart insertion order, while the bulk discount job sorts by discount magnitude. The fix refactors both code paths to use a shared helper method that always sorts product IDs ascending before executing the UPDATE, eliminating the circular dependency. Additionally, a @Retryable annotation is added to catch SQLException with SQLState 40P01 and retry up to 3 times with exponential backoff, handling any residual edge cases.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T18:49:41.068386+00:00— report_created — created