Concept · Databases

ACID vs BASE

01

Why this matters

"Strong consistency" and "eventual consistency" are the two ends of a spectrum that drives every data-layer decision. Pick strong when you must (payments, inventory, anything involving money or exclusivity). Pick eventual when you can (feeds, analytics, notifications) — you get far better scale and availability in exchange.

ACID is the vocabulary for strong consistency. BASE is the vocabulary for eventual. Both are sloppy acronyms, but both capture a real tradeoff.

02

ACID unpacked

A — Atomicity. A transaction is all-or-nothing. If one statement in the transaction fails, all changes are rolled back. You never see "the debit happened but the credit didn't."

C — Consistency. (The overloaded word.) Every transaction moves the database from one valid state to another valid state. Foreign keys hold, check constraints hold, unique indexes hold. This is not the same as the "C" in CAP.

I — Isolation. Concurrent transactions don't see each other's partial work. Defined by isolation levels (see variants below). Most databases default to Read Committed; Serializable is the strongest and slowest.

D — Durability. Once committed, a transaction survives crashes, power loss, everything short of disk destruction. Usually via write-ahead log (WAL) synced to disk before commit returns.

03

BASE unpacked

BA — Basically Available. The system always responds to reads and writes. Prefers returning stale or partial data over failing the request.

S — Soft state. The state of the system may change over time even without new inputs — replicas converge asynchronously. Looking at one replica vs another can return different values for a brief window.

E — Eventual consistency. If no new writes happen, all replicas will eventually converge to the same value. "Eventually" is typically milliseconds to seconds, rarely longer.

BASE is what DynamoDB, Cassandra, and Mongo (in default mode) give you. It's the price of being always available during network partitions — see CAP.

04

Isolation levels (ACID's dial)

LevelWhat it preventsWhat it allowsDefault in
Read UncommittedNothingDirty reads (see uncommitted changes)Rarely used
Read CommittedDirty readsNon-repeatable reads (same query returns different rows in one txn)Postgres, Oracle, SQL Server
Repeatable ReadNon-repeatable readsPhantom reads (new rows appear in range scan)MySQL InnoDB
SerializableEverything — as if transactions ran one at a timeNothing unsafeRarely default (costly)

Pick Serializable for financial logic. Pick Read Committed (default) for almost everything else. Tune up only when you hit a specific anomaly.

05

Tradeoffs

ACID

Strong guarantees, harder scale

You write code against invariants ("balance never goes negative"; "order has exactly N items"). The DB enforces them. Bug surface shrinks enormously. Price: strong coordination — every write talks to every replica (or a consensus group), limiting write throughput and regional distribution.

BASE

Massive scale, app-level invariants

Writes commit locally and propagate async → huge throughput, cross-region writes. Price: your app code handles edge cases — "what if the counter increments from 99 → 100 → 99 when replicas converge late?" You write conflict-resolution logic (last-write-wins, CRDTs, vector clocks).

06

Deep dive — the write-skew anomaly

Read Committed is the default but has subtle bugs. The classic: two doctors on-call. The rule: "at least one doctor must be on-call." Both try to remove themselves from on-call concurrently.

  1. Txn A: reads doctors on-call → sees {Alice, Bob}. Decides it's safe for Alice to leave.
  2. Txn B: reads doctors on-call → also sees {Alice, Bob}. Decides it's safe for Bob to leave.
  3. Txn A: updates Alice.on_call = false. Commits.
  4. Txn B: updates Bob.on_call = false. Commits.
  5. Now nobody is on-call. Invariant violated.

This is write skew. Each transaction individually saw a valid state; their interleaving produced an invalid one. Read Committed doesn't prevent it. Serializable does (at ~30–50% throughput cost) — or add a SELECT ... FOR UPDATE to materialize the intent.

Moral: default isolation is fine for 99% of code; the 1% (exclusivity rules, financial invariants) needs explicit locks or Serializable.

07

Used in problems

E-commerce uses ACID for order placement (inventory invariant). Payment gateway uses Serializable for double-charge protection. News feed uses BASE for engagement counters (like/share counts). Ticketmaster uses ACID with explicit row locks to prevent double-booking a seat.

Next up