The three propertiesCore idea
%%{init: {"look":"handDrawn","handDrawnSeed":7,"theme":"base","fontFamily":"Virgil, \"Segoe Print\", \"Comic Sans MS\", cursive","themeVariables":{"fontFamily":"Virgil, \"Segoe Print\", \"Comic Sans MS\", cursive","fontSize":"16px","primaryColor":"#fff4e6","primaryBorderColor":"#1e1e1e","primaryTextColor":"#1e1e1e","secondaryColor":"#e7f5ff","tertiaryColor":"#ebfbee","lineColor":"#1e1e1e","textColor":"#1e1e1e","mainBkg":"#fff4e6","nodeBorder":"#1e1e1e","clusterBkg":"#f8f9fa","edgeLabelBackground":"#ffffff","actorBkg":"#e7f5ff","actorBorder":"#1e1e1e","noteBkgColor":"#fff9db","noteBorderColor":"#1e1e1e"}}}%%
graph TD
C["Consistency<br/>every read sees the latest write"] --- A["Availability<br/>every request gets a response"]
A --- P["Partition tolerance<br/>works despite network splits"]
P --- C
class C blue
class A green
class P orange
classDef orange fill:#ffd8a8,stroke:#1e1e1e,color:#1e1e1e
classDef blue fill:#a5d8ff,stroke:#1e1e1e,color:#1e1e1e
classDef green fill:#b2f2bb,stroke:#1e1e1e,color:#1e1e1e
classDef red fill:#ffc9c9,stroke:#1e1e1e,color:#1e1e1e
classDef violet fill:#d0bfff,stroke:#1e1e1e,color:#1e1e1e
classDef yellow fill:#ffec99,stroke:#1e1e1e,color:#1e1e1e
classDef grey fill:#e9ecef,stroke:#1e1e1e,color:#1e1e1eConsistency (C)
Every read gets the most recent write, or an error. All nodes see the same data at the same time. Example: after you change your profile picture, every request shows the new one.
Availability (A)
Every request gets a non-error answer, though maybe not the latest data. Example: even before your new picture reaches every server, profile requests still work, briefly showing the old one.
Partition tolerance (P)
The system keeps working when the network splits nodes apart. Machines crash, cables get cut, switches fail: in a distributed system this is not optional.
The trade-off: C or A during a partitionCompare
Because network partitions can't be avoided, the real choice is what to do while one is happening:
%%{init: {"look":"handDrawn","handDrawnSeed":7,"theme":"base","fontFamily":"Virgil, \"Segoe Print\", \"Comic Sans MS\", cursive","themeVariables":{"fontFamily":"Virgil, \"Segoe Print\", \"Comic Sans MS\", cursive","fontSize":"16px","primaryColor":"#fff4e6","primaryBorderColor":"#1e1e1e","primaryTextColor":"#1e1e1e","secondaryColor":"#e7f5ff","tertiaryColor":"#ebfbee","lineColor":"#1e1e1e","textColor":"#1e1e1e","mainBkg":"#fff4e6","nodeBorder":"#1e1e1e","clusterBkg":"#f8f9fa","edgeLabelBackground":"#ffffff","actorBkg":"#e7f5ff","actorBorder":"#1e1e1e","noteBkgColor":"#fff9db","noteBorderColor":"#1e1e1e"}}}%%
graph TB
subgraph CP["CP: stay consistent"]
direction LR
c1["Node 1"] -.-|link down| c2["Node 2"] --> r1["reject:<br/>error or timeout"]
end
subgraph AP["AP: stay available"]
direction LR
a1["Node 1"] -.-|link down| a2["Node 2"] --> r2["answer anyway:<br/>may be stale"]
end
CP ~~~ AP
class c1,c2 blue
class a1,a2 green
class r1 red
class r2 yellow
classDef orange fill:#ffd8a8,stroke:#1e1e1e,color:#1e1e1e
classDef blue fill:#a5d8ff,stroke:#1e1e1e,color:#1e1e1e
classDef green fill:#b2f2bb,stroke:#1e1e1e,color:#1e1e1e
classDef red fill:#ffc9c9,stroke:#1e1e1e,color:#1e1e1e
classDef violet fill:#d0bfff,stroke:#1e1e1e,color:#1e1e1e
classDef yellow fill:#ffec99,stroke:#1e1e1e,color:#1e1e1e
classDef grey fill:#e9ecef,stroke:#1e1e1e,color:#1e1e1eCP systems (consistency + partition tolerance)
During a partition, refuse requests rather than serve stale data. Availability is given up to stay consistent.
HBase
Strongly consistent; requests fail during partitions.
MongoDB (majority writes)
Guarantees consistency but may reject writes.
ZooKeeper
Consensus-based; unavailable during leader election.
Google Spanner
Globally consistent, using TrueTime clocks.
AP systems (availability + partition tolerance)
During a partition, keep answering, possibly with stale data. Consistency is given up to stay available.
Cassandra
Always writable; eventually consistent.
DynamoDB
Highly available; eventually consistent by default.
CouchDB
Multi-master replication with eventual consistency.
DNS
Always resolves, but may return stale records.
CA systems
Only possible when there are no partitions: a single node, or a perfectly reliable network (which does not exist). A single PostgreSQL server is CA.
A real-world decision frameworkHow it works
%%{init: {"look":"handDrawn","handDrawnSeed":7,"theme":"base","fontFamily":"Virgil, \"Segoe Print\", \"Comic Sans MS\", cursive","themeVariables":{"fontFamily":"Virgil, \"Segoe Print\", \"Comic Sans MS\", cursive","fontSize":"16px","primaryColor":"#fff4e6","primaryBorderColor":"#1e1e1e","primaryTextColor":"#1e1e1e","secondaryColor":"#e7f5ff","tertiaryColor":"#ebfbee","lineColor":"#1e1e1e","textColor":"#1e1e1e","mainBkg":"#fff4e6","nodeBorder":"#1e1e1e","clusterBkg":"#f8f9fa","edgeLabelBackground":"#ffffff","actorBkg":"#e7f5ff","actorBorder":"#1e1e1e","noteBkgColor":"#fff9db","noteBorderColor":"#1e1e1e"}}}%%
graph TD
Q1{"is stale data<br/>acceptable?"} -->|no| CP["choose CP<br/>ZooKeeper, HBase"]
Q1 -->|yes| Q2{"is downtime<br/>acceptable?"}
Q2 -->|no| AP["choose AP<br/>Cassandra, DynamoDB"]
Q2 -->|"yes, single node"| CA["CA<br/>single-node PostgreSQL"]
class Q1,Q2 yellow
class CP blue
class AP green
class CA grey
classDef orange fill:#ffd8a8,stroke:#1e1e1e,color:#1e1e1e
classDef blue fill:#a5d8ff,stroke:#1e1e1e,color:#1e1e1e
classDef green fill:#b2f2bb,stroke:#1e1e1e,color:#1e1e1e
classDef red fill:#ffc9c9,stroke:#1e1e1e,color:#1e1e1e
classDef violet fill:#d0bfff,stroke:#1e1e1e,color:#1e1e1e
classDef yellow fill:#ffec99,stroke:#1e1e1e,color:#1e1e1e
classDef grey fill:#e9ecef,stroke:#1e1e1e,color:#1e1e1e| System | Choice | Why |
|---|---|---|
| Banking | CP | You can’t show a wrong balance. Reject the transaction instead. |
| Social media feed | AP | A feed a few seconds old is fine; users care that it always loads. |
| Shopping cart | AP | From the Amazon Dynamo paper: better an item appears twice than disappears. |
| DNS | AP | A slightly old IP address beats no answer. |
| Leader election | CP | There must be exactly one leader, even if that means a short outage. |
PACELC: the extension to CAPScale
PACELC adds the normal case: if there is a Partition, choose A or C; Else, choose Latency or Consistency. Even without failures, keeping replicas in sync costs time.
| Class | During a partition | Normally | Examples |
|---|---|---|---|
| PA/EL | Availability | Low latency | Cassandra, DynamoDB |
| PA/EC | Availability | Consistency | MongoDB |
| PC/EL | Consistency | Low latency | PNUTS (Yahoo) |
| PC/EC | Consistency | Consistency (higher latency) | Google Spanner |
Common interview mistakesPitfalls
SummarySummary
| Type | During a partition | Normal operation | Examples |
|---|---|---|---|
| CP | Reject requests | Strong consistency | ZooKeeper, HBase, Spanner |
| AP | Serve stale data | Low latency | Cassandra, DynamoDB, DNS |
| CA | N/A (no partitions) | Strong consistency + high availability | Single-node PostgreSQL |
Frequently asked questionsFAQ
What does the CAP theorem actually guarantee?
During a network partition between nodes, a distributed system must choose between consistency, every read returning the latest write, and availability, every request returning a valid though possibly stale response. It cannot promise both while the partition lasts; after it heals, nothing prevents both.
Is the CAP trade-off relevant in normal operation?
Not most of the time: CAP applies only during partitions, so the choice describes behavior in failure. Labels like CP and AP say what happens when nodes split, not a permanent property in steady state, which is why engineers treat it as failure design rather than a daily toggle.
How do engineers actually choose CP versus AP?
Decide from the product: a payment ledger prefers CP, while a like counter tolerates AP eventual consistency. In practice systems combine both, such as a strong-consistency primary for critical data plus asynchronously replicated caches, so the answer is per-feature rather than system-wide.

Now explain cap theorem to me out loud
I'll give you a design problem and push on the trade-offs, like a real interviewer.

