When two of your servers can't talk to each other, you have to choose: keep answering with maybe-stale data, or refuse to answer until they reconnect. This chapter turns that one painful choice into a vocabulary — CAP, PACELC, and the spectrum of consistency models in between.
Every distributed system makes one promise it can't fully keep: that all its copies of your data agree, instantly, all the time. The network won't allow it. This chapter is about being honest — and deliberate — about exactly which part of that promise you break, and when.
We'll start by pinning down what "consistency" even means here (it's a slippery word with two different jobs). Then we'll see why making copies of data is what creates the whole problem in the first place. From there: CAP made concrete, PACELC's everyday correction to it, the full spectrum of consistency models, the session guarantees that fix the most common bug, and finally how real systems tune the knob — strong for money, eventual for feeds.
"Consistency" is one word doing two unrelated jobs, and conflating them causes endless confusion. Before we go further, let's separate them.
balance = 50 on one machine; if I read from another machine right now, do I see 50, or do I see the old 40? This is the C in CAP, and it's the one this whole chapter is about.Plain-English version of the distributed sense: "if I just changed something, will everyone — including me — see the change?" When the answer is "always, immediately," you have strong consistency. When the answer is "eventually, give it a moment," you have eventual consistency. Everything in this chapter lives between those two poles.
Here is the uncomfortable truth: if your data lived in exactly one place, on one machine, there would be no consistency problem at all. There's only one copy, so it can't disagree with itself. The instant you make a second copy, you've created the possibility that the two copies hold different values — and the whole tension of this chapter is born.
But you can't keep just one copy. Chapter 1 already forced your hand: you replicate the database for read capacity, and you spread copies across regions so a single data-center fire doesn't end the company. Replication isn't optional — it's the price of being fast and surviving failure. And the moment data lives in more than one place, copies can disagree.
Why do they disagree? A write lands on one copy and has to travel to the others, and that trip takes time — milliseconds across a rack, tens of milliseconds across a continent. During that travel window, a reader hitting a not-yet-updated copy sees stale data. Network hiccups, slow links, and outright outages stretch that window from "barely noticeable" to "indefinite." Consistency, then, is fundamentally a question about how you manage the gap between copies — how long you tolerate it, and what you do when the gap can't close.
The CAP theorem names three things you'd love to have, all at once:
The pop-culture version — "pick any two of three" — is misleading. Here's the honest version. Partitions are not optional. Networks really do drop packets, cables really do get cut, and a switch really does reboot mid-deploy. You don't get to "choose" not to tolerate partitions any more than you get to choose not to have weather. So P is a given. The real theorem is about what happens during a partition:
When a partition splits your nodes, you can keep one of C or A, not both. Either a node on the cut-off side keeps answering with the data it has (choosing A, possibly stale), or it refuses to answer until it can confirm it's current (choosing C, becoming unavailable). That's the entire choice.
Concretely:
CAP only talks about the dramatic moments — partitions — which, for a well-run system, are rare. But there's a tradeoff you pay all day, every day, even when the network is perfectly healthy, and CAP says nothing about it. PACELC fixes that omission.
Read it as two clauses:
Why is there still a choice when nothing is broken? Because making copies agree before you answer takes time. If you want a read to reflect the very latest write, you may have to wait for several replicas to confirm they're current — that's extra round trips, that's latency. If instead you answer from the nearest replica right now, you're fast but you might serve data that's a few milliseconds behind. Strong consistency literally costs milliseconds on every single request.
That's why PACELC matters more day-to-day than CAP: partitions are occasional, but the latency-vs-consistency dial is turned on every read and write you ever serve. The notation pairs the two choices, e.g. PA/EL ("available under partition, low-latency otherwise") or PC/EC ("consistent always, latency be damned").
"Strong vs eventual" is a useful headline, but the real world is a gradient with many named stops in between. Each stop is a different promise the system makes about what your reads can see. From strongest (and slowest) to weakest (and fastest):
Read-your-writes and monotonic-reads belong to a friendly family called session guarantees — promises scoped to one user's session rather than the whole system. They're cheap to provide and they kill the most-felt anomalies, which is why they're the next section.
Here's the anomaly everyone has felt: you post a comment, the page refreshes, and your comment is gone. You didn't do anything wrong. What happened is the write went to the primary, but your refresh's read got routed to a replica that hadn't caught up yet — so it honestly reported "no comment here." A few seconds later it appears, which makes it feel like a ghost.
The full strong-consistency fix (make every reader everywhere see your write instantly) is expensive overkill. You don't need the whole world to see your comment immediately — you just need you to. That narrower promise is read-your-writes consistency: within your own session, any read reflects your own prior writes.
It's cheap to implement because it's scoped to one session. Common tricks:
Pair read-your-writes with monotonic reads (never show older data than already seen) and the everyday experience feels rock-solid — even though, behind the curtain, the system is still only eventually consistent for everyone else.
Consistency isn't a single switch you flip for the whole system — it's a dial, and modern stores let you turn it per operation. The mechanism most systems expose is the quorum.
Say each piece of data is stored on N replicas. On a write you require W of them to acknowledge before you call it done; on a read you ask R of them and take the newest answer. The magic rule (we'll prove it in Chapter 7) is:
W + R > N ⟹ strong consistency
If the write set and the read set must overlap, then any read is guaranteed to touch at least one replica that saw the latest write — so it can't miss it. Crank W and R up and you get strong consistency at the cost of latency; drop them (e.g. W=1, R=1) and you get blazing speed but only eventual consistency. Same cluster, different dial position per request.
That's why the right mental model isn't "is my system CP or AP?" but "which consistency does this particular operation need?" Almost every real product mixes both:
The same company runs both at once: Amazon keeps your shopping cart highly available (AP — never lose an add-to-cart), but processes the final payment with strong consistency (CP — never double-charge).
The code below models the read side of a quorum: given the values returned by the replicas you queried, decide what to hand back. Two strategies, both common in the wild — last-write-wins (trust the highest timestamp) and a max-merge (for a value that only ever grows, like a counter, take the largest). Flip languages; the shape is identical.
Putting it all together, here's a quick decision guide. Walk it per operation, not per system.
W+R>N) or a single-leader store.The senior move isn't memorizing CAP — it's noticing that "consistency" is a per-operation budget, and spending it where wrong answers hurt while saving it everywhere else.