Databases

Backend · Databases

Consistency Models: Strong, Eventual & Causal

Consistency isn't a checkbox — it's a spectrum of promises about what a reader is allowed to see, and each point on it costs something different.

8 min read
Consistency ModelsDistributed SystemsCAP Theorem

Ask "is this database consistent?" and you'll get a yes-or-no answer that hides almost everything interesting. Once data is replicated across machines — and in any system built for availability or scale, it is — consistency stops being a single property and becomes a spectrum of guarantees about what a reader can observe after a write. A consistency model is just the precise statement of where on that spectrum a system sits: which orderings of operations it promises to preserve, and which it lets slide.

Understanding that spectrum matters because every point on it trades latency and availability for predictability. Picking the wrong one either wastes money on guarantees nobody needed, or ships a bug that only shows up when two requests land on different replicas milliseconds apart.

Strong consistency: one copy, as far as anyone can tell

Strong consistency — more precisely, linearizability — promises that every read sees the most recent completed write, and that all clients agree on the order operations happened in. Once a write returns successfully, no subsequent read, from any client, on any replica, can return a staler value. Functionally, the system behaves as if there were only one copy of the data, even though there might be five, spread across three continents.

That illusion is expensive to maintain. Enforcing it across regions typically means every write has to be acknowledged by a quorum of replicas — or funneled through a single leader — before it's considered durable, and reads often need to check in with that same leader or quorum to avoid returning stale data. The latency cost is a speed-of-light problem, not an engineering one: a write from Singapore that must be confirmed by a replica in Virginia is going to take at least as long as the round trip, no matter how well the software is written. Strong consistency is the right default for anything where "probably correct" isn't good enough — account balances, inventory counts, seat reservations — but paying for it everywhere, including on data nobody needs ordered so tightly, is how systems end up slow for no benefit.

Eventual consistency: it'll get there

Eventual consistency relaxes the promise considerably: if no new writes come in, all replicas will eventually converge on the same value — but there's no bound on how long "eventually" takes, and no guarantee about what a read returns in the meantime. Write to one replica in São Paulo, immediately read from a replica in Tokyo, and you might get the old value. Not because anything is broken, but because the update simply hasn't propagated yet.

Whether that's acceptable depends entirely on what the data represents. A social media like-count that briefly reads 4,382 instead of 4,383 costs nothing — nobody notices, and the number corrects itself within milliseconds to seconds. A bank balance that briefly reads a hundred dollars higher than it should is a different problem entirely: it's an invitation to overdraw an account before the "eventually" arrives. The value of eventual consistency is that it buys availability and low latency — every replica can serve reads and accept writes independently, even during a network partition — but that trade only pays off when the business can tolerate a visible window of staleness.

Stale reads aren't a bug, they're the contract

A common mistake is treating a stale read from an eventually consistent store as a defect to be patched. It isn't — it's the model working as designed. If a stale read is actually unacceptable for a given piece of data, that's a sign the data needs a stronger consistency model, not a sign the eventually consistent store is misbehaving.

Causal consistency: order where order matters

Between those two extremes sits a genuinely useful middle ground. Causal consistency guarantees that operations which are causally related are seen in the same order by every replica, while operations that are unrelated — concurrent — can be observed in different orders on different replicas without breaking anything. The canonical example is a comment thread: if someone replies to a comment, every reader must see the original comment before the reply. Nobody should ever see a reply appear before the thing it's replying to. But two unrelated top-level comments posted around the same time can legitimately show up in a different order for different readers — neither one depends on the other, so there's nothing to preserve.

The reason causal consistency is attractive is that it captures almost all of the ordering that actually matters to a human reading the data, while still allowing replicas to accept writes locally and sync up lazily — it doesn't need the global coordination that linearizability demands. Systems implement it by tracking dependencies (often with version vectors or explicit "happens-before" metadata attached to each write) and making sure a replica never applies an operation before the operations it depends on have already landed.

Client-side guarantees: consistency as experienced, not just stored

Even on top of an eventually consistent store, there are cheaper, client-scoped guarantees that go a long way toward a sane user experience. Read-your-writes consistency promises that a client will always see its own writes reflected in its subsequent reads — you post a comment and refresh the page, and it must be there, even if a stranger reading the same page from another replica might not see it yet. Monotonic reads promises that once a client has seen a value, it will never see an older value on a later read — no flickering backward in time as requests happen to land on different replicas.

Neither of these requires strong consistency system-wide; both are usually implemented by pinning a client to the replica it last wrote to or read from, or by having the client track a version token and refusing to accept a response older than what it's already seen. They're cheap, and they eliminate the specific bugs that make an eventually consistent system feel broken to the person using it, even when the underlying replication is working exactly as designed.

Back to CAP: this is the vocabulary for what you chose

The CAP theorem tells you that during a network partition, a system has to give up either consistency or availability — it draws the boundary of what's achievable. What it doesn't tell you is what "consistency" means in practice once you've made that trade. That's exactly what these models are for: strong consistency, eventual consistency, and causal consistency are the precise vocabulary for describing the guarantee a system actually provides, so that "we chose availability over consistency" turns into something an engineer can design against — read-your-writes here, causal ordering there, full linearizability only where the cost is justified.

Key takeaways

  • Consistency is a spectrum of guarantees about what a reader can observe, not a single yes/no property.
  • Strong consistency (linearizability) makes replicas behave like one copy, at the cost of cross-region latency.
  • Eventual consistency trades a bounded staleness window for availability and speed — fine for like-counts, dangerous for balances.
  • Causal consistency preserves order only between causally related operations, letting unrelated ones reorder freely.
  • Read-your-writes and monotonic reads are cheap, client-scoped guarantees that fix the most user-visible symptoms of eventual consistency.
  • CAP defines what's achievable under a partition; consistency models are the vocabulary for what you actually chose to build.
2026 — Built by Arpit Mishra