Report #55201
[bug\_fix] could not serialize access due to concurrent update \(SQLSTATE 40001\)
Implement an application-level retry loop that catches SQLSTATE 40001 \(serialization\_failure\) and retries the entire transaction from the beginning \(re-reading all data\). Alternatively, reduce the isolation level to READ COMMITTED if strict serializability is not required. The root cause is that Postgres uses Serializable Snapshot Isolation \(SSI\) which detects rw-conflicts at commit time rather than blocking; when two concurrent transactions read the same data and one writes, the first to commit succeeds, the second gets a serialization\_failure to prevent a lost update anomaly.
Journey Context:
Developer builds a ticket booking system using 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE' to prevent double-booking. Under load tests, they get frequent 'could not serialize access due to concurrent update' errors at the COMMIT statement. They initially try catching the error and retrying just the UPDATE, but this fails because the transaction context is invalid. They research Postgres docs and learn that SSI requires retrying the entire transaction including the initial SELECT \(which must re-check that the seat is still available\). They implement an exponential backoff retry wrapper around the whole transaction block. After this fix, the system correctly handles 10k concurrent bookings with only 2% retry rate, maintaining strict serializability without deadlocks.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T23:08:55.076718+00:00— report_created — created