ACID in 2 minutes

ACID is what a relational engine guarantees for a transaction on a single node. The catch: most of its sharp edges live in how you use it — transaction scope, isolation level, and where the durability boundary actually sits.

A — Atomicity

A transaction is all-or-nothing. If any step fails or the server crashes mid-flight, every change inside the transaction is rolled back as if it never happened. The canonical example is a money transfer: the debit and credit either both happen, or neither does. On crash, the WAL replay on restart reverses incomplete transactions to keep this promise.

C — Consistency

Each transaction moves the database from one valid state to another, where “valid” means the constraints you declared: foreign keys, NOT NULL, CHECK, UNIQUE. No constraint, no consistency — the engine doesn’t know your business rules unless you wrote them down.

C is the weakest letter. Härder and Reuter, who coined ACID in 1983 (building on Jim Gray’s earlier transaction work), basically said the same — A + I + D plus your declared constraints is what C means in practice. The engine doesn’t add anything magical here. Don’t confuse it with CAP-consistency (linearizability across nodes); different concept entirely.

I — Isolation

Concurrent transactions shouldn’t step on each other. The SQL standard defines four levels — Read Uncommitted, Read Committed, Repeatable Read, Serializable — each preventing more anomalies (dirty reads, non-repeatable reads, phantom reads). The default is rarely as strong as people assume:

EngineDefault isolation
PostgreSQLRead Committed
MySQL / InnoDBRepeatable Read
SQL ServerRead Committed
OracleRead Committed

A concrete anomaly worth memorising: write skew. Two transactions read the same set, each decides its write is safe based on the other not having committed yet, both commit. Snapshot Isolation doesn’t catch it. The textbook example: two on-call doctors both go off-call simultaneously because each sees the other still on. Only Serializable prevents it.

Isolation has a real cost. Stricter = less concurrency. Most production apps run at Read Committed and reach for SELECT ... FOR UPDATE or advisory locks on the few critical paths.

D — Durability

Once COMMIT returns, the change survives — even an immediate power loss. Postgres guarantees this by appending the change to the Write-Ahead Log and fsync-ing before acknowledging.

Two caveats people get burned by:

ACID across common databases

Not every “transactional” database guarantees all four letters. Quick matrix:

DatabaseACID
PostgreSQL
MySQL / InnoDB
SQLite
SQL Server
Oracle
CockroachDB
Google Spanner
MongoDB multi-doc since 4.0 validators / unique only
DynamoDB ≤100 items per tx type / conditional only
Redis MULTI/EXEC has no rollback no schema single-threaded requires AOF/RDB
Cassandra LWT for single-key CAS

What ACID does not give you

TL;DR: ACID is a single-node contract about what survives a crash. Distributed correctness, race conditions, and business rules are still on you.

← database engineering