SQLSTATE 40001 ERROR Class 40: Transaction Rollback

serialization_failure could not serialize access due to concurrent update — 40001

PostgreSQL error "could not serialize access due to concurrent update" (SQLSTATE 40001): what it means, common causes, and how to fix it.

PG 12, 13, 14, 15, 16, 17, 18 Official docs
Last reviewed May 2025 Grounded in source

Diagnostic Queries

Symptoms

A REPEATABLE READ or SERIALIZABLE transaction tried to update a row that another transaction modified and committed after this transaction’s snapshot was taken. To preserve isolation, PostgreSQL aborts your transaction rather than overwrite the change.

  • The transaction is aborted with SQLSTATE 40001 and must be retried.
  • Only happens under REPEATABLE READ or SERIALIZABLE isolation.
  • Common on hot rows (counters, balances) updated by many sessions.

What the server log shows

ERROR:  could not serialize access due to concurrent update
STATEMENT:  UPDATE accounts SET balance = balance - 100 WHERE id = 1;

Why PostgreSQL raises this — what the manual says

Section 13.2.2 Repeatable Read Isolation Level:

“a repeatable read transaction cannot modify or lock rows changed by other transactions after the repeatable read transaction began.”

Under snapshot isolation, each transaction sees a frozen view of the database. If a row it wants to write was changed by a concurrent committed transaction, applying the write would violate isolation, so PostgreSQL raises 40001. This is a normal, expected outcome under high-isolation levels — the correct response is to retry.

Common causes

  • Concurrent updates to the same row under REPEATABLE READ/SERIALIZABLE.
  • Read-modify-write patterns without retry logic.
  • Hot rows (counters, balances) updated by many sessions.

How to fix it

  1. Catch 40001 and retry the whole transaction — this is the intended pattern.
  2. Keep high-isolation transactions short to shrink the conflict window.
  3. For hot counters, consider READ COMMITTED with row locks, or aggregate writes.
  4. Add jittered backoff between retries to avoid thundering herds.

Related & next steps

Reference: PostgreSQL 18 Section 13.2.2 “Repeatable Read Isolation Level”.

Was this helpful?