CAP theorem

What consistency, availability and partition tolerance mean, why the real choice is only between the first two during a network split, how to pick per feature, and how quorums tune the trade-off.

On this page
  1. 01The three words
  2. 02What the choice looks like
  3. 03Choose per feature
  4. 04Consistency is a dial
  5. 05How to say it
  6. 06Common mistakes
  7. Check yourself

Keep the same data on more than one machine and you get a question that has no free answer: when the machines cannot talk to each other, what should each one do? The CAP theorem is the name for that question. In a design discussion it is a way to say, per feature, which kind of wrong you prefer.

Crux: networks split, so a replicated system must choose between refusing some requests (consistent) and answering with possibly stale data (available). The choice applies during the split, and you make it per feature.

The three words

  • Consistency (C). Every read sees the most recent write, as if there were one copy. Often called linearizability. This is not the "C" of ACID, which is about keeping data rules (constraints) true.
  • Availability (A). Every request to a working node gets a real answer, not an error or a timeout.
  • Partition tolerance (P). The system keeps working when the network between nodes drops or delays messages, so nodes cannot all see each other.

The theorem (Gilbert and Lynch proved it, after Brewer's conjecture) says you cannot have all three when a partition happens.

The popular reading, "pick any two of three", misleads. Partitions are not optional. Networks fail. A system spread over more than one machine cannot choose to have no partitions, so in practice P is a given and the real choice is C or A.

A single-node database has no partition between replicas, so the theorem has nothing to say about it.

What the choice looks like

consistent (CP) write x = 2 node 1x = 2 node 2x = 1 cut read x error: try againcorrect, but not available available (AP) write x = 2 node 1x = 2 node 2x = 1 cut read x x = 1 (stale)answers, but not up to date
Node 1 took a write of x = 2, then the link to node 2 was cut. A read arrives at node 2. It can refuse, or answer with old data.
  • Choose consistency (CP). Node 2 cannot prove it has the latest value, so it refuses (or waits). The caller gets an error. Nothing wrong is ever shown, and some requests fail. In practice the side that cannot reach a majority stops accepting writes.
  • Choose availability (AP). Node 2 answers with what it has. Everyone gets an answer, and some answers are stale. When the network heals, the nodes must reconcile the differences (last write wins, version vectors, or merge rules such as combining two shopping carts).

Remember that this is about the moment of the split. Without one, you can have all three, and you pay in other ways: the next section.

Choose per feature

Do not say "my system is AP". Say which parts need what.

  • Prefer consistency when a wrong answer costs money or trust: account balances, seat or ticket booking, the last item in stock, unique usernames, who holds a lock or which node is the leader.
  • Prefer availability when a stale answer is fine and an error is not: a social feed, like counts, product browsing, view counters, a shopping cart (adding an item twice is better than refusing to add).

A quick test: if two users briefly saw different data, would anyone lose money, safety or trust? If yes, lean consistent. If the worst outcome is a like count off by a few for a few seconds, lean available.

One system usually needs both. In a food-ordering app: taking payment and assigning the last unit of a limited item are consistent; the restaurant list, photos and reviews come from replicas and may lag. Order tracking sits between: it can be a little stale, but it should never go backwards (monotonic reads).

For a booking system: "seat selection is consistent, because two people must not hold the same seat, so during a partition we refuse some bookings. Browsing shows event pages from replicas and may be a few seconds old." That sentence shows you understand the trade-off.

Consistency is a dial

Between "always the latest" and "eventually the same" there are useful stops.

  • Strong (linearizable). Reads see the latest write. Needs coordination, so it is slower and unavailable during a split.
  • Read your writes. After you write, you see your own change. Enough for most user-facing screens (your profile after an edit), and cheap to do by reading your own writes from the primary.
  • Monotonic reads. You never see time go backwards between two reads.
  • Causal. If B was caused by A, everyone sees A first (a reply never shows before its post).
  • Eventual. Replicas converge if writes stop, with no promise about when.

Strong consistency also has a price without a partition: every write waits for replicas to confirm. That extension is often called PACELC: if there is a Partition choose A or C, Else (no partition) choose Latency or Consistency.

Quorums

With N replicas, a write waits for W acknowledgements and a read asks R replicas. If R + W > N, every read set overlaps every write set in at least one node, so a read sees the latest write.

N = 3, W = 2, R = 2:   2 + 2 = 4 > 3   overlap guaranteed → reads see the latest write
N = 3, W = 1, R = 1:   1 + 1 = 2 < 3   no overlap          → fast, but may read stale data

Lowering W makes writes faster and more available and raises the chance of stale reads. It is the dial in a Dynamo-style store, and it is how you say, with a number, which side you picked. (Even with R + W > N, other issues such as concurrent writes can still produce surprises; do not oversell it.)

Mechanisms that lean each way

  • Toward consistency: a single node or a single leader that takes all writes, synchronous replication (a write is acknowledged only after replicas have it), a consensus protocol (Raft, Paxos) for leader election and configuration, or a distributed transaction across stores (two-phase commit: correct, but slow, and it blocks if the coordinator dies). Many databases offer a strongly consistent read mode, at higher latency; check the current docs for the one you name.
  • Toward availability: replicas fed asynchronously (reads served from copies that may lag), change data capture to feed search or caches from the main store, writes accepted on more than one node and reconciled later, deployment across several zones so one failure does not stop reads.
  • The price of each. Consistency costs latency, throughput and some availability, and is capped by a single source of truth. Availability costs stale reads, reconciliation logic and the user-visible oddities that come with it.

How to say it

  • Raise it while stating the non-functional requirements, once per feature that matters, not as a lecture.
  • Say that partitions happen, so the choice is between C and A.
  • Choose per feature, with a reason in terms of what a wrong answer costs.
  • State the behaviour in the split: "the minority side rejects writes" or "both sides accept writes and we merge".
  • Name the mechanism: single leader with synchronous replicas for strong, quorum for tunable, asynchronous replication for eventual.

Common mistakes

  • "Pick two of three", as if P could be skipped.
  • Labelling a whole system CP or AP instead of its features.
  • Confusing CAP's consistency with ACID's.
  • Saying "eventual consistency" without saying how long it can last, or what the user sees meanwhile.
  • Applying one model to the whole system, then being unable to explain the feature that needs the other.
  • Believing a single database with one primary and async replicas is strongly consistent for reads from replicas. It is not.
  • Forgetting that availability here is a technical property of each request. A system that is up 99.99% of the time is not the same claim.

Check yourself

  • Why is "pick two of CAP" misleading?
  • What does a CP system do in a partition, and what does an AP system do?
  • Pick CP or AP for each, with a reason: seat booking, a like counter, a shopping cart, a unique username.
  • With N = 5, W = 3, R = 3, do reads see the latest write? What about W = 2, R = 2?
  • What does "read your writes" give a user, and how can you build it cheaply?
  • What does PACELC add to CAP?