Overview

Isolation is the “I” in acid. SQL defines four levels; PostgreSQL implements three distinct ones. Pick the level per transaction by which anomaly would corrupt your data, such as double-booking or lost updates. Stronger levels abort transactions with SQLSTATE 40001, so the application must retry the whole transaction.

Rules

  • Isolation is built on mvcc snapshots in PostgreSQL. Read Committed (the default): each statement sees data committed before it began. Read Uncommitted behaves identically, so PostgreSQL never allows dirty reads.
  • Repeatable Read: one snapshot for the whole transaction. PostgreSQL’s version also prevents phantom reads, but write skew is still possible.
  • Serializable: behaves as if transactions ran one at a time, using serializable snapshot isolation. It aborts a transaction when it detects a dependency cycle.
  • Use Read Committed for most OLTP. Use Repeatable Read or Serializable for read-then-write decisions such as booking and reconciliation, and avoid Serializable on hot write paths unless you need it.
  • Higher levels add no row locks for reads; deadlocks still come from explicit locking and write order (deadlock).
BEGIN ISOLATION LEVEL SERIALIZABLE;
SELECT count(*) FROM slots WHERE date = '2026-06-01';  -- one slot left
INSERT INTO bookings (date, user_id) VALUES ('2026-06-01', 42);
COMMIT;  -- fails with 40001 if a concurrent transaction took the last slot; retry