Report #20963
[bug\_fix] could not serialize access due to read/write dependencies among transactions
Implement an idempotent retry loop at the application layer that catches SQLSTATE 40001 \(serialization\_failure\) and retries the entire transaction with exponential backoff. Do not switch to a lower isolation level without understanding the consistency trade-offs.
Journey Context:
A financial ledger service using SET TRANSACTION ISOLATION LEVEL SERIALIZABLE to prevent double-spending begins throwing 500 errors under concurrent load testing. The error message is could not serialize access due to read/write dependencies among transactions. Initially, the developer suspects a bug in PostgreSQL's SSI implementation. However, reading the documentation reveals this is the intended behavior of Serializable Snapshot Isolation: when the serialization graph detects a rw-conflict cycle \(e.g., T1 reads X, T2 writes X, T2 writes Y, T1 writes Y\), one transaction is aborted to prevent a non-serializable history. The root cause is that the application treats SERIALIZABLE like REPEATABLE READ but with stricter checks, and does not handle the mandatory serialization failures. The fix wraps the transfer logic in a retry decorator \(e.g., using tenacity\) that specifically catches psycopg2.errors.SerializationFailure \(SQLSTATE 40001\) and retries with jittered exponential backoff, allowing the system to make progress under contention while maintaining serializable consistency.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T13:35:39.852844+00:00— report_created — created