The CAP Theorem, proposed by Eric Brewer, states that a distributed database system can only guarantee two of the following three properties at the same time:
C — Consistency
A — Availability
P — Partition Tolerance
👉 A distributed system cannot guarantee all three simultaneously — it must sacrifice at least one.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CAP Theorem — Interactive</title>
<style>
.infographic-captheorem {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #16a34a;
--good-soft: #dcfce7;
--on-accent: #ffffff;
--display-font: Georgia, 'Iowan Old Style', serif;
--body-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--mono-font: 'SF Mono', Consolas, monospace;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 700px;
margin: 0 auto;
box-sizing: border-box;
overflow-x: hidden;
}
.infographic-captheorem[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4ade80;
--good-soft: #123420;
--on-accent: #101418;
}
.infographic-captheorem * { box-sizing: border-box; }
.cap-head { text-align: center; margin-bottom: 0.25rem; }
.cap-head h2 {
font-family: var(--display-font);
font-size: 1.9rem;
margin: 0 0 0.5rem;
}
.cap-head p {
color: var(--ink-soft);
font-size: 0.98rem;
margin: 0 auto;
max-width: 540px;
line-height: 1.55;
}
.cap-diagram-scroll { overflow-x: auto; margin-top: 1.5rem; }
.cap-diagram-scroll svg { width: 100%; height: auto; display: block; min-width: 320px; }
.cap-tri-line { stroke: var(--line); stroke-width: 2; fill: none; }
.cap-tension-arrow { stroke: var(--ink-soft); stroke-width: 3; opacity: 0.5; transition: opacity 0.3s, stroke 0.3s; }
.cap-tension-arrow.is-active { stroke: var(--accent); opacity: 1; }
.cap-edge-highlight { stroke: var(--accent); stroke-width: 5; fill: none; opacity: 0; transition: opacity 0.3s; stroke-linecap: round; }
.cap-edge-highlight.is-visible { opacity: 1; }
.cap-node { cursor: pointer; }
.cap-node-circle {
fill: var(--paper); stroke: var(--ink-soft); stroke-width: 2.5; transition: fill 0.3s, stroke 0.3s, transform 0.2s;
transform-origin: center;
transform-box: fill-box;
}
.cap-node:hover .cap-node-circle { transform: scale(1.06); }
.cap-node.is-selected .cap-node-circle { fill: var(--accent); stroke: var(--accent); }
.cap-node.is-excluded .cap-node-circle { stroke: var(--line); }
.cap-node-letter {
font-family: var(--display-font); font-weight: 700; font-size: 26px; text-anchor: middle; fill: var(--ink);
pointer-events: none; transition: fill 0.3s;
}
.cap-node.is-selected .cap-node-letter { fill: var(--on-accent); }
.cap-node-label {
font-family: var(--body-font); font-size: 13px; font-weight: 700; text-anchor: middle; fill: var(--ink);
pointer-events: none;
}
.cap-node.is-excluded .cap-node-label { fill: var(--ink-soft); text-decoration: line-through; }
.cap-center-label {
font-family: var(--display-font); font-size: 15px; font-weight: 700; text-anchor: middle; fill: var(--ink-soft);
pointer-events: none;
}
.cap-hint {
text-align: center; font-size: 0.85rem; color: var(--ink-soft); margin-top: 1rem; font-style: italic;
}
.cap-panel {
margin-top: 1.5rem; background: var(--paper-alt); border: 1px solid var(--line); border-radius: 10px;
padding: 1.1rem 1.25rem; display: none; animation: cap-panel-in 0.35s ease;
}
.cap-panel.is-visible { display: block; }
@keyframes cap-panel-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
.cap-panel-title { font-family: var(--display-font); font-size: 1.05rem; margin: 0 0 0.5rem; color: var(--accent); }
.cap-panel-body { font-size: 0.9rem; line-height: 1.55; color: var(--ink); margin: 0 0 0.7rem; }
.cap-panel-examples {
font-size: 0.8rem; color: var(--ink-soft); background: var(--paper); border: 1px solid var(--line);
border-radius: 7px; padding: 0.5rem 0.7rem; display: inline-block;
}
.cap-reset-row { display: flex; justify-content: center; margin-top: 1.1rem; }
.cap-reset-btn {
font: inherit; font-size: 0.82rem; background: var(--paper); border: 1px solid var(--line);
border-radius: 7px; padding: 0.5rem 1rem; cursor: pointer; color: var(--ink); display: none;
}
.cap-reset-btn.is-visible { display: inline-block; }
.cap-reset-btn:hover { border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
.infographic-captheorem *, .infographic-captheorem *::before, .infographic-captheorem *::after {
transition-duration: 0.001ms !important; animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-captheorem" id="captheorem">
<div class="cap-head">
<h2>The CAP Theorem</h2>
<p>In a distributed system, you can only fully guarantee <b>two</b> of these three at once. Pick any two corners below to see what you're giving up.</p>
</div>
<div class="cap-diagram-scroll">
<svg viewBox="0 0 560 480" role="img" aria-label="CAP theorem triangle with Consistency, Availability, and Partition Tolerance">
<defs>
<marker id="capArrowHead" markerWidth="8" markerHeight="8" refX="4" refY="4" orient="auto">
<path d="M0,0 L8,4 L0,8 z" fill="var(--ink-soft)"></path>
</marker>
<marker id="capArrowHeadActive" markerWidth="8" markerHeight="8" refX="4" refY="4" orient="auto">
<path d="M0,0 L8,4 L0,8 z" fill="var(--accent)"></path>
</marker>
</defs>
<!-- triangle outline -->
<polygon class="cap-tri-line" points="280,90 90,400 470,400"></polygon>
<!-- tension arrows along edges (double-headed) -->
<path class="cap-tension-arrow" id="arrowCP" d="M265,105 L105,385" marker-start="url(#capArrowHead)" marker-end="url(#capArrowHead)"></path>
<path class="cap-tension-arrow" id="arrowCAvail" d="M295,105 L455,385" marker-start="url(#capArrowHead)" marker-end="url(#capArrowHead)"></path>
<path class="cap-tension-arrow" id="arrowPA" d="M132,400 L428,400" marker-start="url(#capArrowHead)" marker-end="url(#capArrowHead)"></path>
<!-- highlight overlay for selected edge -->
<path class="cap-edge-highlight" id="highlightCP" d="M270,90 L90,390"></path>
<path class="cap-edge-highlight" id="highlightCAvail" d="M290,90 L470,390"></path>
<path class="cap-edge-highlight" id="highlightPA" d="M100,400 L460,400"></path>
<text class="cap-center-label" x="280" y="270">CAP</text>
<text class="cap-center-label" x="280" y="292">Theorem</text>
<!-- Consistency node (top) -->
<g class="cap-node" id="nodeC" data-key="C" transform="translate(280,90)">
<circle class="cap-node-circle" r="42"></circle>
<text class="cap-node-letter" y="9">C</text>
</g>
<text class="cap-node-label" x="280" y="28">Consistency</text>
<!-- Partition Tolerance node (bottom left) -->
<g class="cap-node" id="nodeP" data-key="P" transform="translate(90,400)">
<circle class="cap-node-circle" r="42"></circle>
<text class="cap-node-letter" y="9">P</text>
</g>
<text class="cap-node-label" x="90" y="465">Partition Tolerance</text>
<!-- Availability node (bottom right) -->
<g class="cap-node" id="nodeA" data-key="A" transform="translate(470,400)">
<circle class="cap-node-circle" r="42"></circle>
<text class="cap-node-letter" y="9">A</text>
</g>
<text class="cap-node-label" x="470" y="465">Availability</text>
</svg>
</div>
<p class="cap-hint" id="capHint">Click any two corners to select them.</p>
<div class="cap-panel" id="capPanel">
<p class="cap-panel-title" id="capPanelTitle"></p>
<p class="cap-panel-body" id="capPanelBody"></p>
<span class="cap-panel-examples" id="capPanelExamples"></span>
</div>
<div class="cap-reset-row">
<button class="cap-reset-btn" id="capReset" type="button">↺ Clear selection</button>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('captheorem');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const info = {
'C+A': {
title: 'Consistency + Availability — sacrificing Partition Tolerance',
body: 'Every request gets an immediate, up-to-date answer — but only because the system assumes the network between nodes never breaks. Once a real partition happens, this combination isn\u2019t achievable at scale: you can only keep it on a single node, or a network reliable enough to basically never split.',
examples: 'Example: a single-instance relational database (no replication).'
},
'C+P': {
title: 'Consistency + Partition Tolerance — sacrificing Availability',
body: 'When the network splits, the system refuses to answer some requests rather than risk giving out-of-date data — some nodes go silent or return errors until they can resync and agree on the current state.',
examples: 'Examples: MongoDB (default settings), HBase, traditional RDBMS with strict replication.'
},
'P+A': {
title: 'Partition Tolerance + Availability — sacrificing Consistency',
body: 'When the network splits, every node keeps answering every request — but different nodes may be out of sync, so you can get stale or conflicting data until things resync. This is "eventual consistency."',
examples: 'Examples: Cassandra, DynamoDB, CouchDB.'
}
};
const nodes = ['C', 'A', 'P'];
let selected = [];
const hint = document.getElementById('capHint');
const panel = document.getElementById('capPanel');
const panelTitle = document.getElementById('capPanelTitle');
const panelBody = document.getElementById('capPanelBody');
const panelExamples = document.getElementById('capPanelExamples');
const resetBtn = document.getElementById('capReset');
function highlightIdFor(pair) {
const set = pair.slice().sort().join('');
if (set === 'AC') return 'highlightCAvail';
if (set === 'CP') return 'highlightCP';
if (set === 'AP') return 'highlightPA';
return null;
}
function clearHighlights() {
document.querySelectorAll('.cap-edge-highlight').forEach(el => el.classList.remove('is-visible'));
}
function render() {
nodes.forEach(k => {
const el = document.getElementById('node' + k);
el.classList.toggle('is-selected', selected.includes(k));
el.classList.toggle('is-excluded', selected.length === 2 && !selected.includes(k));
});
clearHighlights();
if (selected.length < 2) {
hint.textContent = selected.length === 0
? 'Click any two corners to select them.'
: 'Pick one more corner...';
hint.style.display = 'block';
panel.classList.remove('is-visible');
resetBtn.classList.toggle('is-visible', selected.length > 0);
return;
}
hint.style.display = 'none';
resetBtn.classList.add('is-visible');
const hId = highlightIdFor(selected);
if (hId) document.getElementById(hId).classList.add('is-visible');
let lookupKey;
const set = selected.slice().sort().join('');
if (set === 'AC') lookupKey = 'C+A';
else if (set === 'CP') lookupKey = 'C+P';
else lookupKey = 'P+A';
const data = info[lookupKey];
panelTitle.textContent = data.title;
panelBody.textContent = data.body;
panelExamples.textContent = data.examples;
panel.classList.add('is-visible');
}
nodes.forEach(k => {
document.getElementById('node' + k).addEventListener('click', () => {
if (selected.includes(k)) {
selected = selected.filter(x => x !== k);
} else if (selected.length < 2) {
selected.push(k);
} else {
selected.shift();
selected.push(k);
}
render();
});
});
resetBtn.addEventListener('click', () => {
selected = [];
render();
});
render();
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});You can pick only two sides of the triangle at a time.
🟦 Let’s Understand Each Term
Property | Meaning |
|---|---|
✅ Consistency (C) | Every read receives the most recent write or an error. No stale data. |
✅ Availability (A) | Every request receives a non-error response — without guaranteeing it's the most recent. |
✅ Partition Tolerance (P) | The system continues to operate even if communication between nodes breaks down (network failure). |
🧩 Why is Partition Tolerance Always Needed?
Because network failures are inevitable in a distributed system (like different data centers, cloud regions, etc.).
So in reality, CAP becomes a choice between:
➡️ Consistency vs Availability during network partitions.
📊 CAP Combinations
Type | What It Means | Example Systems |
|---|---|---|
CP | Consistent + Partition-tolerant: may sacrifice availability | HBase, MongoDB (with strong consistency), Redis (in Sentinel mode) |
AP | Available + Partition-tolerant: may return stale data (no strong consistency) | CouchDB, Cassandra, DynamoDB |
CA ⚠️ (Theoretical) | Consistent + Available: assumes no network failure, not realistic in distributed systems | Single-node DBs (like traditional RDBMS, e.g., MySQL in standalone mode) |
📘 Real-World Example
Imagine a banking system:
Consistency + Partition Tolerance (CP)
Guarantee correct balance, even during failures
But system may deny access until it syncs
Example: MongoDB in strict mode
Availability + Partition Tolerance (AP)
Always respond to users, even during failure
But balance might be outdated (read stale data)
Example: Amazon DynamoDB
Consistency + Availability (CA)
Always correct & available
BUT fails when network partition occurs (not possible in distributed setup)
📌 Summary
Key Point | Explanation |
|---|---|
🔺 CAP Theorem | Tradeoff between Consistency, Availability, and Partition Tolerance |
🌐 Real-world systems | Must tolerate partitions (so tradeoff is between C and A) |
🔄 Design decision | Depends on the system's use case (e.g., banking vs social media) |
📦 Final Thoughts
Choose CP if you need correctness (e.g., finance, banking)
Choose AP if you need availability (e.g., chat apps, product catalogs)
You can't have it all — CAP forces hard decisions in distributed database design.