Correctness-first (ACID) vs availability-first (BASE) — and, within ACID, a ladder of isolation levels most people default through without noticing.
“Is the data consistent?” sounds like a yes/no question. It is not. Consistency is a spectrum of guarantees with wildly different costs, and one of the most common — and most expensive — mistakes in building data systems is assuming you have a stronger guarantee than you actually paid for. This is a refresher on the two philosophies (ACID and BASE) and the ladder of isolation levels inside ACID, because knowing exactly which guarantee you’re standing on is what separates “occasionally corrupts data under load” from “correct.”
ACID: the transaction guarantees
A transaction is a group of operations that should behave as a single unit. ACID is the four properties that make transactions trustworthy:
- Atomicity — all or nothing. Transfer money between accounts and either both the debit and credit happen or neither does. No half-completed transfers, even if the server crashes mid-way.
- Consistency — every transaction moves the database from one valid state to another, respecting all constraints (foreign keys, uniqueness, checks). (Confusingly, this “C” is not the same “consistency” as in CAP — a lasting naming sin.)
- Isolation — concurrent transactions don’t corrupt each other; the result is as if they ran one at a time. This is the subtle one, covered below.
- Durability — once committed, it survives crashes, power loss, and restarts. It’s on disk (and usually replicated).
ACID is the domain of relational databases — Postgres, MySQL, Oracle — and it’s what you want when correctness is non-negotiable: money, inventory, anything where a lost or duplicated write is a real-world problem.
Isolation: the guarantee you’re probably weaker on than you think
Here’s the part that quietly bites experienced engineers. Perfect isolation (every transaction acts as if it’s alone) is expensive, so SQL databases offer a ladder of isolation levels trading safety for speed — the bottom of the diagram. Each level permits certain anomalies:
- Read Uncommitted — you can see other transactions’ uncommitted changes (dirty reads). A value you read might get rolled back and never have “really” existed.
- Read Committed — you only see committed data, but the same query run twice in one transaction can return different results if someone else committed in between (non-repeatable reads). This is the default in Postgres, Oracle, and SQL Server — meaning most applications run here without the author ever choosing it.
- Repeatable Read — rows you’ve read won’t change under you, but new rows matching your query can still appear (phantom reads).
- Serializable — the gold standard: results are guaranteed identical to some serial ordering. Safe, and the most expensive.
The trap: engineers reason about their code as if it runs at Serializable, while it actually runs at Read Committed. Under low load the anomalies rarely surface; under high concurrency they do — the classic “we lost an update / double-charged a customer only in production” bug. This is the race condition from the concurrency post, at the database layer, and the fix is often the same: make the critical read-modify-write atomic, via an explicit higher isolation level, SELECT ... FOR UPDATE, or an optimistic version check.
BASE: trading consistency for availability
At scale, and across many machines, strong ACID guarantees get expensive — coordinating atomicity and isolation across nodes means network round-trips and blocking. So a whole family of systems makes the opposite bet: BASE — Basically Available, Soft state, Eventually consistent. Instead of guaranteeing every read sees the latest write right now, BASE systems guarantee they’ll converge to a consistent state eventually, while staying available and scalable in the meantime.
This is the CAP theorem made concrete. When a network partition happens, you can be consistent or available, not both — and BASE systems (Cassandra, DynamoDB, Riak) generally choose availability, accepting that a read might briefly return stale data. “Eventually consistent” is not a bug or a weaker product; it’s a deliberate design choice that buys enormous scale and uptime, appropriate when a few seconds of staleness is harmless (a like count, a product view tally) and wrong when it isn’t (an account balance).
The key discipline: know which one you have, and match it to the data. Putting financial transactions on an eventually-consistent store, or forcing strong global consistency on a high-scale activity feed, are both expensive mismatches.
The AI/cloud relevance
Distributed AI systems inherit all of this. The moment your system spans multiple nodes or regions — which any real inference or data platform does — you’re choosing consistency models whether you name them or not. A feature store read that’s eventually consistent might serve a model stale features, silently degrading predictions in a way no error log will show. A vector database that’s eventually consistent might not have indexed the document you just wrote when the very next query looks for it — the “I ingested it but RAG can’t find it yet” bug is often eventual consistency, not a broken pipeline.
Idempotency is the BASE-world safety net. When exactly-once delivery is too expensive (it usually is — more on that in the queues post), systems settle for at-least-once and make operations idempotent so duplicates are harmless. That’s living gracefully with weak guarantees instead of pretending you have strong ones.
Agent state and memory. As agentic systems accumulate persistent state across steps and sessions, “did this agent see the latest state?” becomes a real consistency question. Two agents acting on stale shared state is the distributed race condition again — and the answer is the same menu: stronger isolation where correctness demands it, idempotency and convergence where availability matters more.
The takeaway
“Consistent” is not one thing. ACID gives you correctness-first transactions, but even there you’re usually running at an isolation level weaker than you assume, and the anomalies are real, not academic. BASE trades immediate consistency for availability and scale — a legitimate, powerful choice when staleness is tolerable. The whole game is knowing which guarantee you actually have and matching it to how much correctness the data demands. Get that mapping right and your system is both fast and correct where it counts; get it wrong and you’ll meet the anomalies in production, at load, on the data you could least afford to corrupt.