Report #61569
[bug\_fix] ERROR: could not serialize access due to concurrent update
Implement an application-level retry loop that catches SQLSTATE 40001 \(serialization\_failure\), rolls back the current transaction, and retries with exponential backoff. The root cause is the use of REPEATABLE READ or SERIALIZABLE isolation levels where the database's MVCC implementation detects that a concurrent transaction has committed a modification to a row that the current transaction has already read, preventing the lost update anomaly by aborting the current transaction.
Journey Context:
A Java Spring Boot team builds a banking ledger service. To ensure strict consistency during account balance updates, they set \`@Transactional\(isolation = Isolation.REPEATABLE\_READ\)\`. Under load testing with JMeter simulating 100 concurrent transfers between the same two accounts, they see a surge of exceptions: \`PSQLException: ERROR: could not serialize access due to concurrent update\`. The developers initially think it's a deadlock and try reordering operations, but the error persists. They check the SQLSTATE and find it is 40001 \(serialization\_failure\), distinct from 40P01 \(deadlock\). They research PostgreSQL documentation and learn that in REPEATABLE READ, if Transaction A reads row 1, and Transaction B updates row 1 and commits, then Transaction A attempts to update row 1, it must fail to prevent lost updates. They implement a Spring Retry \`@Retryable\` annotation specifically for PSQLException containing "could not serialize", with a max of 3 attempts and exponential backoff \(100ms, 200ms, 400ms\). The serialization failures still occur statistically but are retried transparently, allowing the application to converge on successful commits without manual intervention.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T09:50:02.425786+00:00— report_created — created