Introduction

To keep an app fast and resilient, you copy your data onto several machines — replicas — spread across the world. If one falls over, another answers. So far so good.

Now a cable is cut, a router dies, a data center drops off the map. The replicas are still running, still serving users, but they can't talk to each other. This is a network partition, and in a system of any real size it is not an "if" but a "when."

In that instant you face a choice you cannot dodge. A write lands on one side of the split. Do you let the other side keep answering reads — risking that it hands back stale data? Or do you refuse to answer until the replicas reconcile — keeping the data correct but going partly offline? You cannot have both. That is the CAP theorem, and it is not a bug to be fixed.

Force the Choice

Below are two replicas of a single value, A and B, that normally stay in sync. Hit Cut the network to partition them. Now write a new value to A — and try to read it from B. B never received the write.

<p class="hint">{{hint}}</p>
<div class="mode">
  <span>{{mode_label}}</span>
  <button id="cp" type="button" class="active">{{btn_cp}}</button>
  <button id="ap" type="button">{{btn_ap}}</button>
</div>
<div class="net" id="net">
  <div class="node" id="nodeA">
    <div class="tag">{{tag_a}}</div>
    <div class="val" id="valA">v0</div>
  </div>
  <div class="link" id="link">{{link_in_sync}}</div>
  <div class="node" id="nodeB">
    <div class="tag">{{tag_b}}</div>
    <div class="val" id="valB">v0</div>
  </div>
</div>
<div class="status" id="status">{{status_healthy}}</div>
<div class="btns">
  <button id="cut" type="button">{{btn_cut}}</button>
  <button id="write" type="button">{{btn_write}}</button>
  <button id="read" type="button">{{btn_read}}</button>
  <button id="heal" type="button" class="ghost">{{btn_heal}}</button>
</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
.mode { display: flex; align-items: center; gap: .5rem; margin: .2rem 0 .8rem; font-size: .9rem; flex-wrap: wrap; }
.mode button { background: #fff; color: #1d3557; border: 1px solid #1d3557; padding: .3rem .7rem;
               border-radius: 8px; font: 600 13px system-ui, sans-serif; cursor: pointer; }
.mode button.active { background: #1d3557; color: #fff; }
.net { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: .6rem; margin: .6rem 0; }
.node { background: #e8eef3; border: 1px solid #cdd9e3; border-radius: 10px; padding: .7rem; text-align: center; }
.tag { font-size: .78rem; color: #5a7088; font-weight: 600; margin-bottom: .3rem; }
.val { font: 700 24px ui-monospace, monospace; color: #1d3557; }
.val.stale { color: #c98a00; }
.link { font-size: .8rem; color: #0a7d33; font-weight: 600; text-align: center; white-space: nowrap; }
.link.cut { color: #c92f3c; }
.net.cut { position: relative; }
.status { font-size: 1rem; font-weight: 600; margin: .5rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
.status.warn { color: #c98a00; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
// Code not found

Pick a mode before you read. In CP (consistency over availability), B refuses to answer while partitioned — your data is never wrong, but the read fails. In AP (availability over consistency), B answers immediately with whatever it last knew — the read succeeds, but the value is stale. There is no third button that gives you a fresh, correct answer from B: the write simply hasn't crossed the cut. Heal the partition and the replicas reconcile.

The Real Result

CAP is often summarized as "pick two of three," but the precise statement is sharper — and it is proven, not conjectured.

  • The three properties. Consistency (every read sees the most recent write — technically linearizability), Availability (every request to a working node gets a non-error response), Partition tolerance (the system keeps operating even when messages between nodes are lost).
  • The theorem. In 2000 Eric Brewer stated it as a conjecture; in 2002 Seth Gilbert and Nancy Lynch turned it into a formal theorem: no distributed data store can simultaneously guarantee all three. During a partition, you must sacrifice C or A.
  • Why the proof works. Suppose two replicas are partitioned. A client writes to one side; another client immediately reads from the other. If the read returns the new value, a message must have crossed the partition — contradiction. So the read either returns a stale value (sacrificing C) or doesn't return at all (sacrificing A).
  • The honest reading. Partitions are a fact of physics, not a design choice — so the real question is never "C, A or P?" but "when a partition happens, do I choose CP or AP?" When the network is healthy, you can have both C and A.

This is the same flavor of proven impossibility as the halting problem: not a gap in our cleverness, but a wall established by a theorem.

Where It Matters

CAP is not academic trivia — it is the first fork in the road when designing any system that lives on more than one machine:

  • CP systems choose correctness. A bank ledger, a lock service, a leader-elected datastore (think etcd, ZooKeeper, or a quorum-based database) would rather reject an operation than risk a wrong balance.
  • AP systems choose uptime. A shopping cart, a social feed, a DNS record, a collaborative document would rather show slightly stale data than show an error — they reconcile later via eventual consistency.
  • Tunable systems let you pick per operation. Databases like Cassandra and DynamoDB expose read/write quorums so the same store can act CP for a payment and AP for a "like."
  • Beyond CAP. The richer PACELC framing adds the everyday trade-off: even with no partition (Else), you still choose between Latency and Consistency.

The same "you can't satisfy every constraint at once" tension shows up across computing — it is the practical cousin of the limits explored in P vs NP.

Conclusion

The CAP theorem is liberating once you accept it. You stop chasing a magic database that is always consistent, always available, and shrugs off network failures — because Gilbert and Lynch proved in 2002 that no such system can exist. Instead you ask the only question that matters: when the network inevitably splits, which do I protect — correctness or availability?

So the next time a system feels like it's "behaving weirdly" during an outage — serving old data, or refusing to answer — remember it may be working exactly as designed. Someone already made the CAP choice for you, and physics made sure they had to.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/cap-theorem/Content licensed under CC BY-NC 4.0.