The eight fallacies told you why distributed systems are hard. The CAP theorem tells you about the specific, unavoidable trade-off that falls out of one of those fallacies (the network is reliable, fallacy 1) when you take it seriously. CAP is the single most-cited and most-misunderstood result in distributed systems. It is on every architecture interview question list, every database vendor’s marketing page, and every “we are eventually consistent” hand-wave in a design meeting.
This lesson does two things. First, it states what the CAP theorem actually says, which is a narrower and more careful claim than the usual interpretation. Second, it walks through the real choices that real systems make, with examples, so the next time someone tells you their database is “AP” you will know what question to ask next.
What CAP actually says
Eric Brewer gave a keynote at the PODC conference in 2000 in which he conjectured that a distributed shared-data system could provide at most two of three guarantees: consistency, availability, and partition tolerance. Seth Gilbert and Nancy Lynch turned that conjecture into a formal theorem in 2002.
The three guarantees, in the precise sense the theorem uses them:
- Consistency (specifically, linearizability): every read sees the most recent write, as if the system had a single up-to-date copy.
- Availability: every request to a non-failing node returns a response in finite time. Not necessarily a fast response, but a response that is not “I refuse.”
- Partition tolerance: the system continues to operate even when arbitrary messages between nodes are lost or delayed indefinitely.
The theorem says you cannot have all three simultaneously. The unhelpful interpretation is “pick two of three,” which has caused more confusion than any other phrase in the field.
The reason “pick two” is wrong is that partition tolerance is not really a choice in any non-trivial distributed system. If your system runs on more than one machine connected by a network, partitions can happen. The fallacies guarantee it. You do not get to opt out of partition tolerance by deciding you would rather have CA. You get to choose what your system does when, inevitably, a partition happens.
So the precise way to read CAP is this: in the presence of a network partition, you must choose between consistency and availability for every operation. Outside of a partition, that trade-off does not apply, and you can have both. CAP is silent on the everyday case. We will fix that with PACELC in the next lesson.
This precise reading has two important consequences. First, it makes “AP system” only half a sentence. AP for which operations? Under which conditions? Many systems are AP for some operations and CP for others, and the operator chooses per call. Second, it makes the question of what your system does during a partition much more concrete than the textbook version. The interesting design work is in the partition behaviour.
The three categories, in practice
Real systems sit in one of three places.
CP: refuse rather than serve stale
A CP system, when it detects a partition, prefers to fail closed. A node that cannot reach a quorum of its peers will refuse new writes (and possibly new reads) rather than serve a value it cannot prove is current. The user gets an error. The data stays correct.
The archetypal CP systems are coordination services: ZooKeeper, etcd, and Consul (in its strongly-consistent mode). These are the systems we use to run leader election, store configuration, and serve as the source of truth for “who owns this lock” in a larger distributed system. They are CP because if you are using them to coordinate, the worst thing they can do is hand out two locks to two nodes that both think they have the lock. In the partition case, refusing the lock is correct; pretending to grant it twice is catastrophic.
The bank-ledger archetype is the same logic. If two regions of a bank’s ledger disagree on whether the account has 100 dollars, and the partition between them prevents reconciliation, the bank’s correct behaviour is to refuse the withdrawal rather than risk both sides authorising one. Better an angry customer than two withdrawals from the same hundred dollars.
CP systems trade availability during a partition for the guarantee that you will never read stale data and never see a write that gets later silently lost. For data where correctness is paramount and availability can be sacrificed temporarily, this is the right call.
AP: serve whatever you have
An AP system, during a partition, prefers to fail open. Every node keeps answering requests using the most recent data it has. When the partition heals, the divergent versions need to be reconciled, either automatically (last-write-wins, vector clocks, CRDTs) or by application-level logic.
DNS is the most familiar AP system in the world. The DNS resolvers in your laptop, your ISP, and the various caches between you and the authoritative server can all hold slightly different versions of a record. There is no single up-to-date copy. The system is “eventually consistent” in the sense that, given enough time and enough TTL expiries, the caches converge on the latest value. But at any given moment, two clients can resolve the same name to two different addresses. The system stays up. The cost is that you sometimes hit yesterday’s answer.
Cassandra, in its default tunable mode, is an AP database. It accepts writes on any replica, propagates them in the background, and uses last-write-wins (with timestamps) to resolve conflicts when two writes for the same key arrive on different sides of a partition. S3 was famously eventually consistent for many years and only added strong read-after-write consistency in 2020.
AP is the right call when staleness is tolerable and unavailability is not. A shopping cart is the canonical example: if two devices add the same SKU to the cart during a partition, you would rather merge the carts later than refuse the operation now. Worst case, the user removes the duplicate. Best case, they never notice.
Tunable: pick per operation
The most useful systems in production are the ones that let you choose, per operation, how strong the consistency needs to be. Cassandra is the textbook example. Each read and each write specifies a consistency level: ONE, QUORUM, ALL, LOCAL_QUORUM, and so on. A QUORUM read combined with a QUORUM write gives you linearizable behaviour as long as a majority of replicas can be reached. A read at consistency level ONE returns the first answer any replica gives you, which may be stale, but is fast and stays available even when most of the cluster is partitioned away.
DynamoDB has a simpler version of the same idea: every read can be either strongly consistent (which costs more and refuses to serve during a partition that affects the relevant partition key) or eventually consistent (cheaper, faster, may return stale).
Tunable systems are how real applications get the best of both worlds. The login flow is read at QUORUM: stale credentials would be a real bug. The “recent activity” feed is read at ONE: a thirty-second-stale feed is fine.
Where partitions actually come from
The CAP theorem is sometimes accused of being academic on the grounds that “real networks rarely partition.” That is not true, especially in cloud environments. The real causes of partition behaviour, on a real production system in 2026, include:
- A whole availability zone losing connectivity for tens of seconds during a routing change.
- A misconfigured security group that blocks intra-cluster traffic on a particular port for one rolling deploy.
- An overloaded coordinator node that drops heartbeats and is incorrectly marked as partitioned by the rest of the cluster.
- A cross-region link that briefly degrades during a fibre repair.
- A bug in a service mesh that causes mutual TLS handshakes to fail for one combination of versions.
The lesson is that partitions in practice are rarely the dramatic “data centre falls into the sea” scenario. They are little ten-second blips that happen often enough that any non-trivial cluster will see one most weeks. CAP is the framework that tells you what your system is supposed to do in those ten seconds.
A decision flowchart
The key question, on every operation, is what to do during a partition: refuse, or serve possibly-stale.
flowchart TD
A[Client makes a request] --> B{Network partition between this node and the rest?}
B -- No --> C[Serve normally: consistent and available]
B -- Yes --> D{What did the operator choose for this operation?}
D -- CP path --> E[Refuse the request, return error]
D -- AP path --> F[Serve from local replica, may be stale]
F --> G[Reconcile after the partition heals]
E --> H[Caller decides whether to retry or fail]
The CP fork is what ZooKeeper, etcd, and a strongly-consistent Spanner read do. The AP fork is what DNS, a default Cassandra read, and an eventually-consistent DynamoDB read do. Real systems have both forks available and let the application pick.
Common misreadings
A few CAP claims that you will see in the wild and that are worth flagging:
- “Our database is CA.” There is no such thing in a distributed system. Single-machine databases (a non-replicated Postgres) are technically CA in the trivial sense that there are no partitions to tolerate, but as soon as you replicate them across machines you must pick a partition behaviour.
- “We are AP, so we are always available.” Not true. You are available during a partition. Outside of one, you are subject to the same failures as anyone else. “Available” in CAP also has a precise meaning: every non-failing node responds. A system can be AP and still be down because all of its nodes failed.
- “Eventual consistency is good enough.” Sometimes it is, sometimes it is not. The question is what the application does when it observes stale data. If the answer is “the user does not notice and the system reconciles,” fine. If the answer is “we double-charge a customer,” not fine.
- “We picked AP for performance.” This is conflating two different trade-offs. AP versus CP is about partition behaviour. Latency versus consistency is the everyday trade-off, and it is the subject of PACELC. Most of the time, when someone says they chose AP for performance, they mean they chose EL (eventual consistency outside of partitions for low latency) and they have not yet thought carefully about what happens during a partition.
The last bullet is what motivates the next lesson.
What CAP misses
CAP is a useful 90% answer and a misleading 100% one. Its blind spot is that it only describes the system during a partition, and your system spends almost all of its time not in a partition. During the everyday case, you are still trading something. The CAP theorem just does not say so.
In 2010, Daniel Abadi pointed this out in a paper and a blog post, and proposed an extension called PACELC. The acronym is awkward and the idea is simple: “if Partition, choose Availability or Consistency; Else, choose Latency or Consistency.” The first half is CAP. The second half is the part CAP forgot.
PACELC turns the design space from a one-axis decision into a two-axis one, and the second axis is the one that actually matters most days, because most days there is no partition. We will spend the next lesson on it, including a four-quadrant classification of the major distributed databases (Cassandra, DynamoDB, Spanner, Riak, FaunaDB) so you can see at a glance which trade-offs each one is making.
For now, the takeaway from this lesson is that the CAP theorem is a useful frame for one specific question (what does your system do during a network partition) and that the answer is per-operation, not per-system. Any time you hear “we are an AP system,” your follow-up question should be “for which operations, with what reconciliation strategy, and what does the rest of the system do?” If the answer is vague, you have just identified an architectural decision that has not been made yet.
Citations and further reading
- Eric Brewer, “Towards Robust Distributed Systems”, PODC keynote, 2000. Slides and discussion archived at
https://www.cs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf(retrieved 2026-05-01). - Seth Gilbert and Nancy Lynch, “Brewer’s conjecture and the feasibility of consistent, available, partition-tolerant web services”, ACM SIGACT News, 2002. The formal proof.
- Eric Brewer, “CAP Twelve Years Later: How the Rules Have Changed”, IEEE Computer, 2012. Brewer’s own retrospective on what the theorem was and was not.
- Martin Kleppmann, “A Critique of the CAP Theorem” (2015), available at
https://arxiv.org/abs/1509.05393. The most thorough technical critique of the standard interpretation. - For the operational behaviour of CP systems: the etcd documentation on quorum and split-brain, and the ZooKeeper “ZAB” protocol description.
- For tunable consistency: Apache Cassandra documentation on consistency levels, and the DynamoDB developer guide section on read consistency. Both retrieved 2026-05-01.