The most cited and most misunderstood idea in distributed systems. Here’s what it actually says, what it doesn’t, and the framework that’s more useful in practice.
Prerequisites: Consistency Models, Availability Time to read: ~16 minutes
Three properties:
The theorem: during a network partition, you must choose between consistency and availability. You cannot have both.
Almost everyone says: “CAP says pick 2 of 3.” This framing is wrong and interviewers notice.
You do not get to choose P. Network partitions are a fact of the physical world — cables get cut, switches fail, a datacenter link saturates, a routing change blackholes traffic. If your system runs on more than one machine, partitions will happen to you whether you planned for them or not.
So “CA” is not an option for a distributed system. The real statement is narrower:
When a partition happens, do you sacrifice consistency or availability?
flowchart TB
P{Network partition<br/>happens} --> C["CP: refuse to serve<br/>on the minority side<br/><br/>Stay correct, become unavailable"]
P --> A["AP: keep serving<br/>on both sides<br/><br/>Stay up, risk divergence"]
And note that the whole theorem only describes the partitioned state, which is a rare condition. It says nothing about how your system behaves the other 99.9% of the time — which is precisely why PACELC exists.
You run a shop with two branches sharing one inventory ledger. The phone line between them goes down.
CP — close the second branch. Only the branch that can reach head office keeps selling. You will never sell the same item twice, but half your customers are turned away.
AP — keep both open. Both branches keep selling from their last known inventory. Everyone gets served. But you might sell the same last item twice, and when the line comes back you must reconcile — refund someone, apologize, or backorder.
Neither is wrong. Which one is correct depends entirely on what the item is. Concert tickets: CP. Coffee: AP.
When partitioned, the minority side stops answering. Typically the side that can’t reach a quorum.
How they behave: writes require a majority acknowledgment. If you can’t reach a majority, you return an error rather than a possibly-stale or possibly-conflicting answer.
Systems: etcd, ZooKeeper, Consul, HBase, MongoDB (with majority write concern), Google Spanner, CockroachDB, most relational databases with synchronous replication.
Use when: correctness is non-negotiable — configuration and service discovery, distributed locks, leader election, financial ledgers, inventory in a limited sale, unique constraints.
🎙️ “I’d use a CP store for the coordination layer. If we can’t reach a quorum, I’d rather return an error than hand out two leases for the same lock.”
When partitioned, every node keeps accepting reads and writes. Divergence is expected and resolved afterwards.
How they behave: any replica accepts a write. Conflicts are reconciled later via last-write-wins, vector clocks, or CRDTs. → Conflict Resolution
Systems: Cassandra, DynamoDB (default), Riak, CouchDB, DNS, most CDNs.
Use when: being unavailable costs more than being temporarily wrong — shopping carts, social feeds, view counts, user sessions, product catalogues, analytics ingestion, IoT telemetry.
🎙️ “The cart is AP. Amazon’s own conclusion was that a cart item briefly reappearing is a far better customer experience than ‘add to cart’ failing during a network event.”
Most modern databases don’t force a global choice — they let you tune it per query, which is how you should think about it too.
Cassandra / DynamoDB quorum tuning:
N = replicas, W = replicas that must ack a write, R = replicas that must respond to a read
W + R > N → strong consistency (the read set overlaps the write set)
W + R ≤ N → eventual consistency, lower latency, higher availability
N=3, W=1, R=1 → fastest, most available, weakest guarantee
N=3, W=2, R=2 → strong, still survives one node failing
N=3, W=3, R=1 → fast reads, but any node failure blocks all writes
→ Quorums
MongoDB: writeConcern: majority + readConcern: majority gives you CP behaviour;
writeConcern: 1 gives you faster, weaker writes.
DynamoDB: eventually consistent reads by default (cheap and fast); ConsistentRead=true costs
2× the read capacity and goes to the leader.
🎙️ The strong answer: “This isn’t one choice for the whole system. Payments use quorum reads and writes; the product catalogue uses eventual reads at a third of the cost and better latency.”
CAP’s weakness is that it only describes partitions, which are rare. PACELC (Daniel Abadi, 2010) extends it to the normal case:
If there is a Partition, choose between Availability and Consistency; Else (normally), choose between Latency and Consistency.
The “else” half is the part that matters day to day. Even with a perfectly healthy network, strong consistency costs latency, because agreement requires round trips — and if your replicas are in different regions, that’s 100–300 ms per write.
| System | PACELC | Meaning |
|---|---|---|
| DynamoDB, Cassandra (default) | PA/EL | Available when partitioned; prioritizes latency normally |
| Cassandra (quorum) | PA/EC | Available when partitioned; pays latency for consistency normally |
| MongoDB (majority) | PC/EC | Consistent always, at the cost of latency |
| Google Spanner | PC/EC | Consistent always — and buys atomic clocks to keep the latency cost small |
| etcd, ZooKeeper | PC/EC | Consistency is the entire product |
| Most RDBMS with async replicas | PC/EL | Primary is consistent; replicas are fast and stale |
🎙️ Using PACELC in an interview is a genuine differentiator: “CAP only tells us what happens during a partition. The more relevant question here is the ‘else’ case — do we pay cross-region latency on every write for strong consistency, or accept eventual consistency and keep writes local? Given a write path that’s user-facing, I’d keep writes local and reconcile.”
Worth knowing, because these are the follow-up questions:
1. It’s not binary in practice. Real systems degrade gradually. A “CP” system might serve stale reads while refusing writes. An “AP” system might restrict which operations it accepts during a partition. Real behaviour is a spectrum.
2. “Available” in CAP is a very strong definition. It means every non-failed node answers every request. A system that answers 99.9% of requests is not “available” in CAP’s formal sense, but is obviously available in the sense you care about.
3. It ignores latency entirely. A system that responds in 30 seconds is “available” by CAP and useless in practice. This is PACELC’s whole point.
4. It says nothing about partial failures, degraded modes, or what happens under load — which is where most real outages live.
5. Partitions are rarer than people imply, and also more common than people think. Within a single datacenter, true partitions are uncommon. Across regions they’re routine. And a GC pause or an overloaded node is indistinguishable from a partition to everyone else — which is a much more frequent event than a cut cable.
You’re designing a hotel booking system. Two data paths, two answers.
Room availability and booking: if two users book the last room during a partition, you have double-booked a real, physical room. Someone arrives at midnight to no bed. → CP. Use a linearizable store for the booking transaction. If we can’t reach quorum, show “we can’t complete your booking right now” — annoying, but recoverable. Overselling isn’t.
Hotel descriptions, photos, reviews, ratings: a stale description harms nobody. → AP. Serve from replicas and a CDN, eventually consistent, always available.
Search results: slightly stale availability in search is fine, as long as the booking step re-checks against the CP store. → AP for search, CP at commit. This pattern — optimistic display, authoritative check at the moment of truth — is extremely common and worth naming explicitly.
🎙️ “I’d make search eventually consistent for speed and availability, then do a strongly consistent check at the point of booking. That gives us fast browsing and correct commits, and the only cost is the occasional ‘sorry, just taken’ at checkout — which users already understand.”
| Choice | Gain | Cost |
|---|---|---|
| CP | No incorrect data, ever; simple reasoning | Downtime during partitions; higher write latency; harder multi-region |
| AP | Always writable; low latency; easy geo-distribution | Conflicts you must resolve; application handles staleness |
| Tunable per query | Pay only where needed | Two mental models in one codebase; easy to get wrong |
| PC/EC with atomic clocks (Spanner) | Global strong consistency | Cost, vendor lock-in, still pays a few ms of commit wait |
QUORUM reads and writes it behaves CP-ish.1. Partition something. Run a 3-node etcd or Cassandra cluster in Docker. Use iptables (or
just pause a container) to isolate one node. Then:
CONSISTENCY ONE): write different values on both sides of the partition. Heal
it. Observe which value survives and why.This 30-minute exercise makes CAP permanent in a way no diagram does.
2. Classify five systems you use. For each, write down: what happens during a partition, and what the “else” (latency vs consistency) choice is. If you can’t answer, read that system’s docs on consistency — it’s always documented and rarely read.