Report #78457
[bug\_fix] could not serialize access due to concurrent update \(SQLSTATE 40001\)
Implement retry logic with exponential backoff specifically for serialization failures \(40001\). Root cause: Under REPEATABLE READ or SERIALIZABLE isolation, if a transaction reads rows that are concurrently modified and committed by another transaction before the first commits, Postgres raises a serialization failure to prevent phantom reads/non-repeatable reads. Unlike deadlocks, this is a normal occurrence under high concurrency in strict isolation levels and must be retried.
Journey Context:
Your fintech app uses SERIALIZABLE isolation to prevent race conditions in account transfers. Under load testing, you see intermittent errors: 'could not serialize access due to concurrent update'. You check the logs and see SQLSTATE 40001. You initially think it's a deadlock \(40P01\) but realize the code is different. Researching PostgreSQL's MVCC, you learn that SERIALIZABLE uses predicate locking and snapshot isolation; when a concurrent transaction commits a change to a row your transaction read, your commit fails to ensure consistency. This is expected behavior, not a bug. You implement a retry decorator that catches 40001 specifically, waits with exponential backoff \(10ms, 20ms, 40ms\), and retries up to 5 times. After deployment, the serialization errors disappear from user-facing responses because the app transparently retries the transaction.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T14:17:02.705881+00:00— report_created — created