Report #15721
[bug\_fix] could not serialize access due to concurrent update \(SQLSTATE 40001\) in Serializable isolation
Implement an explicit retry loop in application code that catches SQLSTATE 40001 \(SerializationFailure\), rolls back the transaction, and retries with exponential backoff and jitter; limit retry attempts to 3-5; ensure transactions are idempotent.
Journey Context:
A developer builds a high-throughput inventory management system using Postgres with 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE' to prevent race conditions in stock reservation without explicit row locking. During a flash sale, the application throws hundreds of 'ERROR: could not serialize access due to read/write dependencies among transactions' \(SQLSTATE 40001\). The developer initially treats this as a deadlock and tries reordering queries, but the errors continue. Reading the Postgres documentation on Serializable Snapshot Isolation \(SSI\), they understand that unlike Read Committed where writers block writers, Serializable isolation detects rw-dependencies \(read-write conflicts\) that could lead to serialization anomalies and aborts one transaction to maintain equivalence to a serial execution. This is expected behavior under contention, not a bug. The developer implements a Python decorator using the 'tenacity' library: @retry\(stop=stop\_after\_attempt\(5\), wait=wait\_exponential\(multiplier=0.1, max=2\), retry=retry\_if\_exception\_type\(psycopg2.errors.SerializationFailure\)\). The transaction logic is wrapped to ensure idempotency \(checking if the reservation was already created before re-attempting\). After deployment, the flash sale handles 10x traffic with only 0.1% of transactions requiring 2\+ retries, and no data inconsistencies. The fix works because Serializable isolation guarantees strict serializability by design, and the application must be prepared to replay aborted transactions to achieve convergence.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T00:50:29.081008+00:00— report_created — created