"Pick two of three" is the version almost everyone learns, and it's subtly wrong in a way that matters: one of the three was never actually optional. The CAP theorem (Eric Brewer, 2000; formally proven by Seth Gilbert and Nancy Lynch, 2002) is a real, proven result about distributed systems — but the popular one-line summary skips past exactly the part that makes it useful in practice.
What the three letters actually mean
The formal proof is precise about all three, and precision here is where most casual explanations quietly go wrong:
- Consistency — every read receives the most recent write or an error. This is specifically linearizability: the system behaves as if there were only one copy of the data, with every operation appearing to happen instantaneously at some point between when it started and finished. This is not the same "C" as ACID's — ACID consistency means a transaction can never leave the database violating its own constraints (foreign keys, unique constraints); CAP consistency is entirely about whether replicas agree with each other. Same letter, two unrelated meanings, and conflating them is one of the most common mistakes in how CAP gets discussed.
- Availability — every request to a non-failing node eventually receives a response. The formal definition doesn't require that response to be fast, or even bounded in time — just that a working node is never forced to simply refuse to answer.
- Partition tolerance — the system keeps operating despite the network arbitrarily losing or delaying messages between nodes.
Why "pick two of three" is the wrong mental model
Partition tolerance isn't a design choice a real distributed system gets to opt out of — a cable gets cut, a switch fails, a data center loses power, and no amount of good engineering makes a network provably partition-proof. The moment a system spans more than one node communicating over a real network, partitions are a fact to survive, not a feature to decline. Which means the actual, practical decision was never "which two of three" — it's what happens during a partition: does the system keep answering and risk two sides disagreeing (favoring Availability), or does it refuse to answer on the side that can't confirm it's current (favoring Consistency)? Every real distributed system is either CP or AP — "CA" describes a system with no partitions to worry about at all, which in practice means a single node, not a distributed one.
CP and AP in real systems
CP — ZooKeeper and etcd are built for coordination (leader election, cluster configuration) using a consensus protocol (ZAB and Raft, respectively) that requires a quorum of nodes to agree before confirming a write; a node on the losing side of a partition simply stops serving rather than risk answering with data that might already be wrong. That's the right trade for their job — a coordination service serving confidently-wrong answers is worse than one that goes briefly silent.
AP — Cassandra and DynamoDB default to staying available on both sides of a partition, accepting writes everywhere and reconciling replicas afterward ("eventual consistency") rather than refusing requests. Both are also tunable, which is the detail flatly "AP database" labels miss: Cassandra lets you request QUORUM consistency on a specific read or write, and a QUORUM write paired with a QUORUM read behaves like a strongly consistent (CP-flavored) operation on that one query — the same database serving both a fast eventually-consistent read and a slower strongly-consistent one, chosen per request, not fixed for the whole system.
PACELC: the part CAP doesn't cover at all
CAP only describes behavior during a partition — network partitions, in practice, are rare. Daniel Abadi's 2012 extension, PACELC, names the trade-off that exists the rest of the time: if Partitioned, choose Availability or Consistency (that's the original CAP) — else, during entirely normal operation, choose Latency or Consistency. Even with a perfectly healthy network, confirming a write across every replica before returning takes longer than confirming it against one — so a system that's CP or AP during a partition still has to separately decide, all the rest of the time, whether it's optimizing for the fastest possible response or the strongest possible guarantee. This is the more complete picture: CAP alone genuinely doesn't describe how a distributed system behaves most of the time, since most of the time nothing is partitioned at all.
Three misconceptions worth retiring
- "NoSQL means AP, SQL means CP." False as a blanket rule — CAP behavior is a property of a specific system's design and configuration, not its query language. Plenty of distributed SQL systems are explicitly AP-leaning, and, as above, both Cassandra and DynamoDB let a single system behave as either depending on the request.
- "CAP's Consistency is the same as ACID's." Covered above — they measure genuinely different things and happen to share a letter.
- "A single-node database has to make a CAP trade-off too." No — CAP is a theorem about systems with more than one node, because partition tolerance only means anything when there's more than one node for the network to separate. See Horizontal vs Vertical Scaling for exactly why this is one of the real, concrete costs of scaling a database horizontally rather than vertically — a single bigger machine never has this problem to begin with, precisely because there's no second copy to disagree with it.
FAQ
Is CAP still relevant, or has it been superseded by PACELC?
Both are relevant, for different halves of the problem — CAP describes the rare but real partition case, PACELC adds the far more common latency/consistency trade-off during normal operation. Neither replaces the other; PACELC is explicitly an extension, not a correction.
Can a system be CP and AP at different times?
Yes, exactly as Cassandra and DynamoDB demonstrate — the CAP classification isn't a fixed label on a whole database product, it's a description of what a specific operation, configured a specific way, actually does when a partition occurs.
What should I actually take away from CAP as a working engineer?
That the question is never "can I have consistency and availability" in the abstract — it's "when this specific network eventually partitions, which of my specific operations can afford to go briefly unavailable, and which absolutely cannot afford to return a wrong answer." That's a decision made per use case, not once for an entire system.