ML
Database

ACID, Demystified: What Each Letter Actually Costs

Atomicity, Consistency, Isolation, Durability — a plain-English tour plus the real-world price tag of each.

June 11, 20258 min readDatabaseTransactions

Almost every engineer can recite ACID. Far fewer can tell you what each letter costs on a production database under load. Let's fix that.

A — Atomicity

A transaction either fully commits or fully aborts. No half-way. The database makes this work via a write-ahead log (WAL): every change is appended to the log before it touches the page. On crash recovery, committed transactions are rolled forward, uncommitted ones are rolled back.

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;  -- both or neither

Cost: every write is effectively written twice (WAL + page). Good databases amortise this with group commit.

C — Consistency

Constraints (FKs, CHECKs, triggers) hold true before and after the transaction. The confusing part: the database enforces the constraints you wrote. It does not guarantee your business logic is correct — that's on you.

I — Isolation

This is the interesting one. The SQL standard defines four levels:

  • READ UNCOMMITTED — allows dirty reads. Almost never used.
  • READ COMMITTED — default in Postgres/Oracle. Prevents dirty reads but allows non-repeatable reads.
  • REPEATABLE READ — default in MySQL. Same row reads the same value twice; phantom rows still possible (in standard SQL — Postgres actually prevents phantoms at this level too).
  • SERIALIZABLE — as if transactions ran one at a time. Slowest; may force retries.

Most apps run on READ COMMITTED and handle the edge cases with SELECT … FOR UPDATE where it matters. Bumping the whole database to SERIALIZABLE "for safety" is a classic premature generalization.

D — Durability

Once COMMIT returns, the change survives a crash. Implementation: fsync the WAL before acknowledging. This is what makes commits feel slow. It's also where "acks=all"-style settings live in distributed databases.

The hidden cost of each letter

  • Atomicity → write amplification (WAL).
  • Isolation → locks, MVCC versions, longer transactions.
  • Durability → disk latency on commit.

When people "go NoSQL for performance," what they're really doing is picking and choosing among these. That's fine, as long as you're explicit about what you just gave up.

SharePostLinkedIn

Reader Discussion

9 replies// weighed in

TopNewestAuthor
Add to the thread
Disagree, agree harder, or share your own experience…
Email instead →markdown okbe kind
  1. Highlighted by author
    Victor Petrov· Senior BackendAgrees

    "removing indexes is the third-year move" — saving this. first year you add, second year you tune, third year you realise half of them have been dead weight slowing every write since that one feature got cut.

    Jun 13, 2025·2 days later
  2. Dan O'Connor· Eng ManagerStory

    N+1 cost us a P1 incident last Black Friday. ONE endpoint was firing 3,400 queries per cart load. Looked fine in dev (3 carts), looked fine in staging (50 carts), production hit 9k QPS to the DB and cardiac arrest. Add load tests.

    Jun 14, 2025·3 days later
  3. Linh Phạm· Java DeveloperAgrees

    @Version optimistic locking is the 80/20 of CRUD apps. genuinely think JPA should make it default-on with a @NoVersion opt-out. the number of last-write-wins races I've debugged in spring boot apps that didn't set it is too damn high

    Jun 16, 2025·5 days later
  4. Mateus Silva· Backend DevAsks

    Q — SELECT FOR UPDATE SKIP LOCKED as a job queue: still a good fit in 2026 or do you reach for a real broker (sqs, rabbit, etc) past a certain QPS? we run ~400 jobs/sec on PG and it's been chill but I'm nervous

    Jun 17, 2025·6 days later
    • Aya Fujimoto· Database Engineer

      We do 11k jobs/sec on PG with SKIP LOCKED + LISTEN/NOTIFY. The thing that breaks first is your job table bloat — set up partman + auto-vacuum tuning before you scale.

      Jun 18, 2025
    • ML
      Minh LeAuthor

      Plus one. The cliff isn't the QPS — it's the visibility-of-dead-rows pattern. SKIP LOCKED holds up if you're disciplined about cleanup.

      Jun 19, 2025
  5. Greta Schäfer· Senior EngineerAgrees

    isolation levels are the part juniors skip and seniors keep underestimating. read committed feels safe; it's not — phantom reads still exist. the moment money is involved, default to repeatable read and benchmark.

    Jun 18, 2025·1 week later
  6. Isabella Costa· Junior EngineerKind words

    saved this. sharing at standup tomorrow — we've had exactly this problem for 2 sprints and nobody on the team had framed it this way 🙏

    Jun 13, 2025·2 days later
  7. Kenta Yamada· Tech LeadAsks

    would love a war-story follow-up. principles are clear; the actual debugging session is where the interesting stuff lives. there's a real shortage of "here's the dashboard, here's the thread we pulled, here's where we got stuck for 90 mins" content.

    Jun 15, 2025·4 days later

Worked on something similar? Email ducminhldm@gmail.com — I read every one. The good ones become future posts.

Comments seeded · live discussion via email