YeetCode
System Design · Fundamentals

CAP Theorem: What You Actually Give Up During a Partition

A precise guide to the CAP theorem — what consistency, availability, and partition tolerance mean, why you only ever choose C or A, and how CP and AP systems behave.

10 min readBy Bhavesh Singh
cap theoremdistributed systemsconsistencyavailabilitypartition tolerancepacelc

This article has an interactive companion

Don't just read it — step through it interactively, one state change at a time.

Practice this topic on YeetCode

Most people repeat the CAP theorem as "pick two of three," and most people are wrong. You never sit down and choose partition tolerance the way you choose a database — network partitions happen whether you plan for them or not. The real theorem is narrower and more useful: the instant a partition splits your cluster, you must give up either consistency or availability, because keeping both is mathematically impossible.

That single sentence decides how ZooKeeper, DynamoDB, Cassandra, and Postgres behave when a switch dies mid-datacenter. Get it precise and the rest of distributed systems stops feeling like folklore.

What the three letters actually mean

Brewer stated CAP as a conjecture in 2000; Gilbert and Lynch turned it into a proved theorem in 2002. Each letter has a technical definition that matters more than the plain-English word.

LetterInformalTechnical meaning
C — Consistency"reads see the latest write"Linearizability: every operation appears to take effect at a single instant between its call and its return, respecting real-time order
A — Availability"the system responds"Every request to a non-failing node returns a non-error response (no guarantee it's the freshest data)
P — Partition tolerance"survives a network split"The system keeps operating even when arbitrary messages between nodes are dropped or delayed

The trap is the word "consistency." CAP's C is not the C in ACID — it means linearizability specifically, the strongest single-object guarantee, where no client can ever observe a stale value once a newer write has returned.

Why you never really "pick" P

Here is the mental model that fixes the "two of three" confusion. A network partition is a fact of nature: cables get cut, switches reboot, a garbage-collection pause makes a node look dead for four seconds. You cannot design partitions away, so P is always on the table. That leaves a two-way choice, and it only fires during a partition:

  • CP — refuse or block requests on the isolated side so no client reads stale data. Consistency preserved, availability sacrificed.
  • AP — keep answering on both sides with whatever data each has. Availability preserved, consistency sacrificed.

The impossibility proof is a one-liner. Split a cluster into two groups that can't talk. A client writes x = 2 on one side. Another client reads x on the other side. That reader either blocks (loses availability) or returns the old x = 1 (loses consistency). A minority partition physically cannot know whether the majority has already acknowledged a newer write, so it can never safely serve fresh data and stay up at the same time.

In the common case — no partition — this dilemma vanishes. Well-built systems deliver both strong consistency and high availability when the network is healthy. CAP describes failure-mode behavior, not a steady-state menu, which is exactly why "pick two" misleads people.

CP or AP? Classifying real systems

The honest answer to "is this database CP or AP?" is almost always "at what setting?" Classification depends on configuration, not the vendor's logo.

SystemDefault leanWhy
ZooKeeperCPZAB consensus; minority partition refuses writes
etcdCPRaft; only the majority side elects a leader
MongoDB (majority writes)CPPrimary steps down when it loses quorum
CassandraAP (tunable)Eventual consistency by default; hinted handoff + read repair
DynamoDBAP (tunable)Eventually-consistent reads by default; strongly-consistent reads cost 2× the read units

Notice how soft those labels are. Cassandra with quorum reads and writes is effectively strongly consistent. MongoDB with w=1 behaves far more like an AP store. DynamoDB flips to CP-flavored behavior the moment you ask for strongly-consistent reads. The label is a starting point; the config is the truth.

Tunable consistency: the R + W > N rule

Cassandra makes the CP–AP dial explicit per query. Every read and write names how many replicas must acknowledge: ONE, QUORUM (a majority), LOCAL_QUORUM (majority within one datacenter), or ALL.

With replication factor N, write consistency W, and read consistency R, this inequality is the whole game:

text
R + W > N → every read set overlaps every write set → strong consistency

The overlap guarantee is geometric: if writes touch W replicas and reads touch R replicas, and R + W exceeds N, the two sets share at least one node — so a read always sees the latest acknowledged write.

text
N = 3, W = QUORUM = 2, R = QUORUM = 2 → 2 + 2 > 3 ✓ strong N = 3, W = ONE, R = ONE → 1 + 1 = 2 ≤ 3 ✗ can read stale

W=ALL gives the strongest durability but a single dead node blocks all writes. W=ONE is fast and stays up under failure but reads can lag. This per-query tunability is why flatly calling Cassandra "AP" is an oversimplification — it slides along the CP–AP axis one query at a time.

PACELC: the framing CAP leaves out

CAP only speaks about the rare partition. But your database makes a consistency trade-off on every single write, partition or not. PACELC (Abadi, 2012) captures that:

If there is a Partition, choose Availability or Consistency; Else, in normal operation, choose Latency or Consistency.

The "else" clause is the everyday reality. Synchronous replication to a quorum costs a network round-trip per write — 1–10 ms inside a datacenter, 50 ms or more across regions. Asynchronous replication returns instantly but leaves replicas temporarily stale. That's the latency-vs-consistency tax you pay even when nothing is broken.

SystemPACELCReading
DynamoDBPA/ELAP under partition, favors latency normally
CassandraPA/ELSame lean — stays up, stays fast, accepts staleness
Google SpannerPC/ECConsistency always; pays the coordination latency

PACELC explains something CAP can't: why a "strongly consistent" system feels slower even on a perfectly healthy network. The consistency isn't free — you're buying it with a round-trip.

The consistency spectrum, strongest to weakest

"Consistency" is not binary. Between linearizable and "eventually maybe" sit several models, and picking the weakest one that still protects your invariants is how you buy back performance.

ModelGuaranteeCost
LinearizabilityOps appear instantaneous, in real-time order (CAP's C)Highest coordination
Sequential consistencyAll nodes see one total order, but not necessarily real-time orderHigh
Causal consistencyPreserves happens-before relationshipsMedium
Eventual consistencyIf writes stop, replicas converge — no ordering promiseLowest

Session guarantees like read-your-writes and monotonic-reads sit inside this spectrum too. The rule: stronger models demand more coordination and cost more latency. Reach for linearizability only where correctness genuinely requires it — a bank balance, an inventory count — and drop to causal or eventual everywhere the business can tolerate a few seconds of skew.

Walkthrough: a partition hits a 5-node Raft cluster

Raft is a textbook CP system, and tracing one partition through it makes the C-vs-A sacrifice concrete. Setup: 5 nodes (n1–n5), n1 is leader, the committed value is x = 10. A switch fails and splits the cluster into a majority {n1, n2, n3} and a minority {n4, n5}.

StepEventMajority {n1,n2,n3}Minority {n4,n5}
1Partition formsStill has leader n1, 3 ≥ quorum of 3No leader reachable, 2 < quorum
2Client writes x = 20 to n1n1 replicates, n2 + n3 ack → committed (3/5)Never sees the write
3Client reads x from n4Election times out; n4 can't win (needs 3 votes) → returns error/timeout
4Partition healsLog has x = 20 committedn4, n5 rejoin as followers
5ReconciliationSends committed log to n4, n5Truncate any conflicting uncommitted entries, replay to x = 20

The minority side chose consistency over availability at step 3: rather than serve the stale x = 10, it errored out. A write commits only after a majority (more than N/2) acknowledges, so a 5-node cluster tolerates 2 node failures — floor((N-1)/2). The price of that safety is a round-trip to a majority on every write: cheap intra-datacenter, painful across regions.

How this shows up in interviews

CAP is rarely a standalone question — it's the lens interviewers use to probe your real design. The strongest signal you can send is recognizing that different parts of one feature can make different CAP choices.

Take the classic prompt: design a globally-distributed shopping cart. The cart itself is a canonical AP use case — a user must be able to add an item even during a partition, and a briefly stale cart is harmless. Model it as a CRDT (an OR-Set, or a grow-only set with tombstones) so concurrent adds and removes from different regions merge deterministically without coordination. Amazon's original Dynamo did exactly this, accepting that a "deleted" item might occasionally resurrect, and resolving conflicts at checkout.

Then the model flips. At checkout, decrementing inventory and charging a card must be linearizable — you cannot sell the last unit twice. Route the commit through a single-region authoritative service backed by serializable Postgres or Spanner transactions. AP for the cart, CP for the commit: that hybrid is the answer interviewers want, and naming it out loud shows you understand CAP as a per-operation decision rather than a database-wide badge.

The other reliable trap is the "pick two" phrasing. If an interviewer says it, correct them gently — partitions aren't chosen, so the real axis is C vs A during a partition — and you've just demonstrated more depth than most candidates reach.

Further learning

Once the theory clicks, see how it constrains real infrastructure in the sibling guides: Caching (where stale reads are a feature), Load Balancing, CDN (eventual consistency at global scale), and Message Queues (how async replication buys availability). Or practice this topic on YeetCode with the interactive roadmap.

FAQ

Does the CAP theorem really mean "pick two of three"?

No, and repeating that phrase is the fastest way to reveal you've only memorized the slogan. You never choose partition tolerance — network partitions are an unavoidable fact of any distributed system. The genuine choice is binary and only activates during a partition: preserve consistency by refusing requests (CP), or preserve availability by serving possibly-stale data (AP). When the network is healthy, most systems provide strong consistency and high availability simultaneously, which is why "two of three" describes a menu that doesn't exist.

What is the difference between a CP and an AP system?

A CP system prioritizes consistency: when a partition isolates part of the cluster, the minority side stops accepting reads or writes rather than risk serving stale data — ZooKeeper, etcd, and majority-write MongoDB behave this way. An AP system prioritizes availability: every reachable node keeps responding on both sides of the partition, accepting that replicas may temporarily disagree until they reconcile — Cassandra and DynamoDB with eventual reads lean this way. Neither is "better"; a coordination service needs CP, a shopping cart or session store is happy with AP.

How is PACELC more useful than CAP?

CAP only describes what happens during the rare partition, but a database makes a consistency trade-off on every write regardless of failures. PACELC adds the missing "else" clause: if there's a Partition, choose Availability or Consistency; Else, in normal operation, choose Latency or Consistency. That captures the everyday cost — synchronous quorum replication adds a network round-trip per write (50 ms+ across regions), while async replication is fast but stale. It's why Spanner (PC/EC) feels slower than DynamoDB (PA/EL) even when nothing is broken.

What does R + W > N guarantee in a quorum system?

In a system with replication factor N, if you require R replicas to acknowledge each read and W replicas to acknowledge each write, then R + W > N forces the read set and write set to overlap on at least one replica. That overlapping node is guaranteed to hold the most recent acknowledged write, so every read observes it — giving you strong consistency. A typical Cassandra setup uses N=3 with quorum reads and writes (2 + 2 > 3). Drop below the threshold, say R=W=ONE, and reads can miss recent writes, trading consistency for lower latency and higher availability.

Why does CAP's "consistency" not mean the same thing as ACID's "consistency"?

They're unrelated despite the shared word. CAP's C is linearizability — a guarantee about the ordering of reads and writes on a single object across a distributed system, where any read after a completed write sees that write. ACID's C is about database invariants — that a transaction moves the database from one valid state to another, never violating constraints like foreign keys or balance-can't-go-negative. You can have one without the other, so when an interviewer says "consistency," pin down which one they mean before answering.

Make it stick: run this one yourself

Don't just read it — step through it interactively, one state change at a time.

Practice this topic on YeetCode