Report #53730
[bug\_fix] ERROR: could not serialize access due to concurrent update \(40001\)
Implement an application-level retry mechanism that catches SQLSTATE 40001 \(SerializationFailure\) and retries the entire transaction from the beginning with exponential backoff, ensuring the transaction logic is idempotent.
Journey Context:
A Python Django fintech application uses ATOMIC\_REQUESTS and sets the isolation level to 'serializable' for a funds-transfer endpoint to prevent write skew anomalies. Under load testing, many requests fail with 'could not serialize access due to concurrent update' \(SQLSTATE 40001\). The developer initially thinks this is a bug in Postgres. Researching the Serializable Snapshot Isolation \(SSI\) implementation in Postgres reveals that this error is the intended behavior: when the database detects a rw-conflict \(two transactions read data that one then writes\), it aborts one transaction to guarantee serializable equivalence. This is not a deadlock \(which is 40P01\) but a serialization failure. The fix requires changing the application logic from 'open transaction, do work, commit' to a retry loop: BEGIN; work; COMMIT; except SerializationFailure: rollback; retry. The developer implements a decorator using tenacity to retry on psycopg2.errors.SerializationFailure with wait=wait\_exponential\(\). After implementing, the load tests pass with higher latency \(due to retries\) but no 500 errors, maintaining strict serializable consistency. The fix works because Serializable isolation in Postgres uses optimistic concurrency control \(conflict detection at commit time\); applications must handle the inevitable aborts by retrying.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T20:40:52.089899+00:00— report_created — created