Skip to content
Navigation

Type at least two characters. Search covers page titles, headings, tags and database names.

↑ ↓ to navigateEnter to openEsc to close0 pages
Introductionbeginner

ACID and BASE

What each ACID property guarantees in practice, what BASE really describes, and why the two are ends of a spectrum rather than opposing camps.

3 min readBeginnerUpdated Edit this page

ACID

Atomicity. A transaction either applies completely or not at all. Implemented with a write-ahead log or undo log: if the process dies mid-transaction, recovery rolls the partial work back.

Consistency. The database moves from one valid state to another, where "valid" means your declared constraints hold — foreign keys, check constraints, unique indexes. Note that this is the database enforcing your rules; it is unrelated to the C in CAP.

Isolation. Concurrent transactions do not observe each other's partial work. How much isolation you actually get depends on the isolation level, which is almost never the strictest one by default. See Transactions and Isolation Levels.

Durability. Once a commit is acknowledged, it survives a crash. This is where the guarantee is most often weaker than assumed — durability holds against process failure only if the write reached stable storage, and against node loss only if it reached another node.

BASE

BASE describes systems that relax ACID to stay available:

  • Basically Available — the system responds to requests, possibly with stale or partial data.
  • Soft state — state may change over time without new input, as replicas converge.
  • Eventual consistency — given no new writes, all replicas eventually agree.

BASE is not a protocol or a standard. It is a label for the design point that prioritises availability and latency over immediate agreement, and it was coined largely as a rhetorical counterpart to ACID.

The spectrum in practice

Real engines are not in one camp:

EngineSingle-object writesMulti-object transactions
PostgreSQL, MySQLACIDACID, up to serializable
MongoDBAtomic per documentMulti-document transactions available, more expensive
CassandraAtomic per partition-key rowLightweight transactions only (Paxos, per partition)
RedisAtomic per commandMULTI/EXEC batches without rollback semantics
ClickHouseAtomic per insert blockNo general-purpose transactions
CockroachDB, YugabyteDBACIDACID, distributed, serializable

The practical question is never "is this ACID". It is: what is the unit of atomicity, and does my data model fit inside it?

If your invariants fit inside a single document, MongoDB gives you atomicity for free. If they fit inside one Cassandra partition, batched writes to that partition are atomic. If they span entities, you need real transactions — or a design that tolerates temporary inconsistency and repairs it.

Working without multi-object transactions

When the engine cannot span your invariant, the application must:

  • Model to avoid it. Put data that must change together in the same document, row or partition. This is the cheapest fix and the reason document and wide-column modelling is denormalised.
  • Use idempotent operations. If a step can be safely retried, a partial failure becomes a retry rather than corruption.
  • Use an outbox. Write the state change and an event row in one local transaction, then publish the event asynchronously. This is how you get exactly-once-looking behaviour across systems without distributed transactions. See Change Data Capture.
  • Compensate explicitly. If step two fails, run a defined compensating action for step one. Sagas are this pattern with a name.