CAP Theorem
Consistency, Availability, Partition Tolerance — pick two. The fundamental trade-off of distributed systems.
Intent & Description
🎯 Intent
Understand the fundamental constraints of distributed systems and make informed architectural decisions about data consistency vs. system availability.
📋 Context
You are building a distributed database or a multi-node service. Network failures will happen — servers lose connectivity, data centers go dark, partitions occur. CAP tells you that during these partitions, you must choose: either serve requests with potentially stale data (AP) or reject requests to preserve data consistency (CP). There is no perfect solution.
💡 Solution
Choose CP when data correctness is critical — banking, inventory, configuration. Reject writes during partitions to prevent divergence. Choose AP when uptime is critical — social media feeds, caching, analytics. Accept stale data during partitions but keep serving. Choose CA only in single-node systems — not truly distributed, avoids partition tolerance requirement entirely. Design with eventual consistency for AP systems — background sync processes converge data over time. Implement conflict resolution strategies — last-write-wins, vector clocks, or application-specific merge logic.
Real-world Use Case
📌 TL;DR
CAP = pick two of Consistency, Availability, Partition Tolerance. Partitions are inevitable, so the real choice is CP (consistency over availability) vs AP (availability over consistency). Choose based on whether correct data or uptime is more critical for your use case.
Advantages
- Provides a clear framework for distributed system design decisions
- Helps set realistic expectations about system behavior during failures
- Guides the choice of appropriate database technologies (e.g., DynamoDB for AP, PostgreSQL for CP)
- Prevents over-engineering by making explicit trade-offs
Disadvantages
- Binary framing can be misleading — real systems operate on a spectrum, not just two choices
- Pick two is theoretically correct but practical systems often adjust consistency per operation
- During normal operation when no partitions exist, both C and A can be achieved
- Does not account for latency trade-offs, which are often more critical in practice
// CAP in practice: Choosing between consistency and availability during a partition
// CP Approach: Prioritize consistency, reject operations during partition
class CPDatabase {
async write(key, value) {
if (this.isPartitioned()) {
throw new Error("Unavailable: cannot ensure consistency during partition");
}
await this.replicateToAllNodes(key, value);
}
async read(key) {
if (this.isPartitioned()) {
throw new Error("Unavailable: cannot ensure consistency during partition");
}
return await this.readFromQuorum(key);
}
}
// AP Approach: Prioritize availability, serve stale data during partition
class APDatabase {
async write(key, value) {
// Write to local node immediately
this.writeToLocal(key, value);
// Async replication (may fail during partition)
this.replicateToOtherNodes(key, value).catch(() => {});
}
async read(key) {
// Always serve from local node, even if stale
return this.readFromLocal(key);
}
// Background sync for eventual consistency
async syncWithOtherNodes() {
// Vector clocks, conflict resolution, etc.
}
}
// Hybrid Approach: Choose per-operation
class HybridDatabase {
async write(key, value, consistency = 'eventual') {
if (consistency === 'strong') {
if (this.isPartitioned()) {
throw new Error("Unavailable: strong consistency requested");
}
await this.replicateToAllNodes(key, value);
} else {
this.writeToLocal(key, value);
this.replicateToOtherNodes(key, value).catch(() => {});
}
}
}