Engineering Notes
Home/Distributed Systems/Fundamentals/CAP Theorem
Distributed Systems · Fundamentals

CAP Theorem

When the network splits a cluster, every distributed data system must choose: refuse requests to stay consistent, or keep answering and risk disagreeing. Partition a three-node cluster and watch the CP and AP choices play out, then add PACELC's everyday latency trade-off.

🕸️ Distributed Systems● Intermediate⏱ 7 min read▶ 2 interactive🛠️ 2 exercises🎤 5 interview Q&As

🎯 What you'll learn

  • Consistency, availability and partition tolerance, precisely
  • Why partition tolerance isn't optional
  • CP vs AP behaviour during a partition, with real examples
  • Per-operation choices and PACELC

1The Three Properties, Defined Precisely

CAP theorem states that a distributed data system can provide at most two of the following three guarantees at the same time, during a network partition:

  • Consistency (C) — every read receives the most recent write, or an error. Every node that responds to a request agrees on the current value; there is no such thing as one node returning old data while another returns new data.
  • Availability (A) — every request to a non-failing node receives a response (not an error, not a timeout) — though not necessarily the most recent write.
  • Partition tolerance (P) — the system continues to operate despite an arbitrary number of messages being dropped or delayed between nodes (a network partition: some nodes can't talk to some other nodes for a while).

The precise, easy-to-misstate claim: you cannot have all three simultaneously once a partition actually occurs. Outside of a partition (the normal, healthy case), a well-built system can absolutely offer both consistency and availability — CAP is specifically a statement about what has to give during a partition, not a permanent, constant tradeoff.

2Why Partition Tolerance Isn't Really an Optional Choice

CAP is often (mis)taught as "pick any 2 of C, A, P" — as if P were a design choice on equal footing with C and A. In a real distributed system, spanning more than one machine, over a real network, partitions will happen — a switch fails, a cable gets cut, a datacenter loses connectivity, a process pauses long enough for peers to consider it unreachable. A system that "chooses" not to tolerate partitions isn't choosing CA over CP/AP — it's simply going to fail completely (become fully unavailable, everywhere) the moment a partition occurs, because it has no defined behavior for that case at all.

This reframes the real question CAP forces onto every distributed system's design: given that a partition WILL eventually happen, when it does, do you sacrifice Consistency or Availability? That's a genuine design choice — CP or AP — made concretely, node by node, for the duration of the partition.

3CP: Choosing Consistency, Sacrificing Availability During a Partition

A CP system, when partitioned, refuses to serve requests it can't guarantee are consistent — some nodes go unavailable (return errors/timeouts) rather than risk serving stale or conflicting data:

text
Cluster of 3 nodes, partitioned into [Node A] | [Node B, Node C]

A CP system:
  - Node A, isolated and unable to confirm it has the latest write, REFUSES
    reads/writes rather than risk serving stale data -> Node A is UNAVAILABLE
  - Nodes B and C, still able to talk to each other, may continue serving
    (if they still have a majority -- see quorum-based systems)

Concrete examples: a strongly-consistent configuration store like etcd or ZooKeeper (used specifically because callers need a guaranteed-current value, e.g. for leader election — serving a stale "who is the leader" answer to two different callers would be actively dangerous) is built CP. A traditional single-primary relational database, when its primary is unreachable, typically refuses writes rather than let a secondary accept writes it can't guarantee are consistent with the primary.

4AP: Choosing Availability, Sacrificing (Strict) Consistency During a Partition

An AP system keeps serving requests on both sides of a partition, accepting that the two sides may temporarily disagree:

text
Same partition: [Node A] | [Node B, Node C]

An AP system:
  - Node A keeps serving reads AND writes using whatever data it has locally
  - Nodes B/C also keep serving reads and writes
  - If a client wrote to Node A during the partition, and another client
    reads from Node B, it may get a DIFFERENT (older, or conflicting) value
  - Once the partition heals, the system must RECONCILE the divergent
    writes (last-write-wins, vector clocks, application-level merge logic,
    etc. -- how reconciliation works is implementation-specific)

Concrete examples: Cassandra and DynamoDB are classically AP-oriented (configurable, but designed to keep serving during a partition, favoring uptime), because for their common use cases (a shopping cart, a metrics store, a social feed) briefly serving slightly-stale data to keep the system responsive is a better tradeoff than an outage. A CDN cache is AP by nature — an edge node cut off from origin keeps serving its (possibly stale) cached content rather than erroring.

During a healthy, unpartitioned state a system can offer both consistency and availability; the moment a partition splits the cluster, a CP system makes the isolated side refuse requests to stay consistent, while an AP system keeps that side serving requests and accepts it may now disagree with the other side, to be reconciled once the partition heals
During a healthy, unpartitioned state a system can offer both consistency and availability; the moment a partition splits the cluster, a CP system makes the isolated side refuse requests to stay consistent, while an AP system keeps that side serving requests and accepts it may now disagree with the other side, to be reconciled once the partition heals

5This Is a Per-System (Often Per-Operation) Choice, Not a Universal Ranking

Neither CP nor AP is "more correct" in the abstract — the right choice depends entirely on what an inconsistent-but-available response would cost versus what an unavailable response would cost, for that specific piece of data:

DataFavorWhy
Bank account balance used to authorize a withdrawalCPServing a stale balance could let someone overdraw; an error is safer than a wrong answer
"Who is the current leader" in a coordination serviceCPTwo callers getting two different "current" leaders can cause split-brain damage
Product view count / "likes" counterAPA slightly stale count is harmless; an outage on every product page load is far worse
Shopping cart contentsAPLosing availability during checkout browsing is worse than briefly showing a slightly stale cart, which is usually reconciled on the next write

Many real systems aren't purely one or the other everywhere — they make this choice per operation or per data type, using a strongly-consistent store for account balances and an eventually-consistent one for view counters, even within the same product.

💡 Example: one PetPal product, two choices
  • Wallet balance (used to pay for vet visits): stored in a CP database. During a partition, the isolated region returns "payments temporarily unavailable" rather than risk spending the same money twice.
  • "12 people viewed this cat tree": AP counter. During a partition each region keeps counting; numbers reconcile later, and nobody is harmed by a stale count.

6PACELC: A Refinement Worth Knowing

CAP technically only describes behavior during a partition — it says nothing about the consistency/latency tradeoff a system makes when there is no partition, which is the vast majority of the time. PACELC extends the idea: if Partitioned, choose Availability or Consistency; Else (normal operation), choose Latency or Consistency. Even with no partition at all, a strongly consistent system typically pays a latency cost (coordinating with other replicas before acknowledging a write) that an eventually-consistent system avoids — so the C-vs-something tradeoff doesn't fully disappear even in the healthy case, it just becomes a latency tradeoff instead of an availability one.

⚠️ Common Pitfalls

  1. Treating "pick 2 of 3" as a literal, always-available menu — partition tolerance isn't optional in a real networked system; the real, constant choice is CP vs AP for what happens when (not if) a partition occurs.
  2. Assuming a system is CP or AP everywhere, uniformly — many real systems make the choice per data type or per operation (strongly-consistent account balances, eventually-consistent view counters, in the same product).
  3. Forgetting CAP only describes partition behavior — during normal, healthy operation, a well-built system can offer both consistency and availability; conflating "CP system" with "always slow or unavailable" misreads the theorem.
  4. Ignoring the reconciliation problem in an AP design — choosing availability during a partition defers, but doesn't eliminate, the need to actually reconcile divergent writes once the partition heals; a design that hand-waves this isn't actually finished.
  5. Not considering PACELC's latency dimension — evaluating a database purely on its partition-time CAP category while ignoring its normal-operation consistency/latency tradeoff misses a large part of the real-world cost difference between systems.

📋 Quick Reference

text
C = Consistency: every read sees the latest write (or an error) -- all nodes agree
A = Availability: every request to a healthy node gets a non-error response
P = Partition tolerance: system keeps functioning despite dropped/delayed messages

P is NOT optional in a real network -- partitions WILL happen
Real choice: when partitioned, sacrifice C (go CP) or sacrifice A (go AP)?

CP examples: etcd, ZooKeeper, traditional single-primary RDBMS (refuses writes when isolated)
AP examples: Cassandra, DynamoDB (configurable), CDN edge caches (serve stale rather than error)

PACELC: if Partitioned -> Availability or Consistency; Else -> Latency or Consistency
        (the C-vs-something tradeoff exists even with NO partition, as a latency cost)

🧠 Key takeaways

  • CAP is about behaviour during a partition; in healthy times a system can be both consistent and available.
  • Partitions will happen, so the real choice is CP (refuse to stay correct) or AP (answer and reconcile later).
  • Choose per data type or operation: money and leader election lean CP, counters and carts lean AP.
  • PACELC: even without partitions there's a trade-off between latency and consistency.

🎤 Interview Q&A

Questions interviewers ask about this topic. Answer out loud first, then open a card to compare.

Q1State the CAP theorem.core▾

In a distributed system, during a network partition you must choose between consistency (every read sees the latest write, or an error) and availability (every request gets a non-error response, possibly stale). Partitions are unavoidable, so the real choice is CP or AP behaviour when they happen.

Follow-ups interviewers ask
  • Is CA possible? Only if you assume no partitions, which means a single node, not a distributed system.
Q2Give examples of CP and AP systems.core▾

CP: ZooKeeper, etcd, HBase, and relational databases with synchronous replication refuse writes when they can't reach a quorum. AP: Cassandra, DynamoDB (default), Riak keep accepting reads/writes and reconcile later. Many systems are tunable per operation.

Follow-ups interviewers ask
  • Is MongoDB CP or AP? With majority write/read concerns it behaves CP; with weaker settings, closer to AP.
Q3What does PACELC add?core▾

If Partition: choose Availability or Consistency; Else (normal operation): choose Latency or Consistency. It captures that even without partitions, stronger consistency costs latency (waiting for replicas).

Follow-ups interviewers ask
  • Example? DynamoDB is PA/EL; Spanner is PC/EC.
Q4How do you choose consistency for different data in one system?senior▾

Per data type and operation: account balances, inventory reservations and unique usernames need strong consistency; likes, view counts, feeds and recommendations tolerate eventual consistency. Mixing is normal.

Follow-ups interviewers ask
  • What's read-your-writes consistency? A user always sees their own updates, even if others see them later.
Q5What's a common misconception about CAP?core▾

That you pick two of three permanently. In reality, you only trade C vs A during partitions, the 'C' in CAP is linearizability (not ACID consistency), and systems offer a spectrum of consistency levels, not a binary.

Follow-ups interviewers ask
  • What consistency models sit in between? Causal, session (read-your-writes, monotonic reads) and bounded staleness.

🛠️ Practice exercises

Each exercise is a file in this topic folder. Code exercises are self-checking: run them and make the checks pass.

✅ Check yourself

Answer the questions — feedback is instant.

1. During a partition, a CP system's minority side…
Consistency over availability.
2. Why isn't 'P' optional in real systems?
The real choice is C vs A when a partition happens.
3. A product view counter is best served by…
A stale count is harmless; downtime isn't.
4. PACELC adds what to CAP?
Else → Latency or Consistency.