CAP Theorem Explained Simply

Consistency, availability & partition tolerance — why you can only pick 2, with real database examples

API DevelopmentJuly 5, 202619 min readBy Keyur Patel

Your database is replicated across two data centers — one in New York, one in London. The network cable between them gets cut. A user in New York writes data. A user in London reads it. What happens? Do they see stale data? Do they get an error? The answer depends on how your database handles the CAP theorem.

CAP is one of those concepts that gets overcomplicated in textbooks. The core idea is simple: when your distributed system can't communicate internally, it has to make a choice. This guide explains that choice in plain language with real databases you've actually used.

What Is the CAP Theorem?

The CAP theorem (proposed by Eric Brewer in 2000, proven in 2002) states that a distributed data store can only guarantee two out of three properties at the same time:

C — Consistency

Every read receives the most recent write or an error. All nodes see the same data at the same time. If you write "balance = $500" and immediately read, you get $500 — never the old value. Think of it like a shared Google Doc where everyone always sees the latest version.

A — Availability

Every request receives a response (not an error), without guarantee that it's the most recent data. The system never says "sorry, I can't answer right now." Think of it like a customer service line that always picks up — even if the answer is slightly outdated.

P — Partition Tolerance

The system continues to operate even when network communication between nodes is lost. Messages between nodes can be dropped, delayed, or reordered. Think of it like two offices that lose their phone connection but both keep working independently.

The theorem says: pick any two. In practice, since network partitions WILL happen in any distributed system (it's physics, not a choice), you're really choosing between C and A when a partition occurs.

The CAP Triangle — You Can Only Pick 2

                  Consistency (C)
                       /\
                      /  \
                     /    \
                    / CP   \
                   / MongoDB\
                  / CockroachDB
                 /   HBase   \
                /──────────────\
               /                \
              /   CA             \
             / PostgreSQL*        \  AP
            /  MySQL* (single)    \ Cassandra
           /   (single node only)  \ DynamoDB
          /─────────────────────────\ CouchDB
    Availability (A) ──────── Partition Tolerance (P)

    * Single-node databases are CA because they can't partition
      (there's only one node). Once distributed, they must choose.

    In distributed systems: P is mandatory
    → Real choice is always between C and A during a partition

Here's the thing most tutorials miss: CA doesn't really exist in distributed systems. Network partitions are a fact of life. If you have data on multiple nodes, eventually the network between them will fail — even if just for a few seconds. When that happens, your system reveals its true nature: CP or AP.

CP vs AP vs CA — With Real Databases

CP — Consistency + Partition Tolerance

"I'd rather return an error than give you wrong data."

During a partition, CP systems stop serving requests to disconnected nodes to ensure every read returns the latest write. Users might get errors or timeouts, but they'll never see stale or conflicting data.

MongoDB

Uses replica sets with a single primary. During a partition, if the primary is isolated, it steps down. The majority partition elects a new primary. Writes to the old primary are rolled back. Consistency is preserved but some requests fail during the election.

CockroachDB

Distributed SQL database that uses Raft consensus. During a partition, nodes in the minority can't reach a quorum and stop accepting writes. Reads from minority nodes may also fail. Strong consistency guaranteed at the cost of availability during partitions.

HBase / ZooKeeper

ZooKeeper requires a majority quorum to operate. During a partition, the minority side becomes unavailable. HBase relies on ZooKeeper for coordination and inherits this CP behavior.

AP — Availability + Partition Tolerance

"I'd rather give you slightly stale data than no data at all."

During a partition, AP systems keep serving requests on all nodes, even though they can't confirm they have the latest data. After the partition heals, they reconcile conflicts (last write wins, vector clocks, CRDTs).

Cassandra

Every node can accept reads and writes. During a partition, both sides continue operating independently. After the partition heals, data is reconciled using timestamps (last write wins). Tunable consistency lets you choose per-query with QUORUM, ONE, ALL.

DynamoDB

Designed for availability. Uses eventual consistency by default — reads might not reflect the most recent write for a few hundred milliseconds. Offers strongly consistent reads as an option (at higher latency and cost).

CouchDB

Uses multi-version concurrency control (MVCC) and allows conflicts. During a partition, both sides accept writes. When reconnected, conflicting documents are flagged for application-level resolution.

CA — Consistency + Availability (Single Node Only)

"I'm always consistent and always available — because I'm one machine that can't partition."

CA only exists for single-node databases. A single PostgreSQL server is both consistent (ACID transactions) and available (always responds). But it's not partition tolerant — if the server dies, everything is gone. Once you replicate it across nodes, you enter CP or AP territory.

PostgreSQL (single node)

ACID-compliant, always consistent, always available. But zero fault tolerance — one server crash and you're down. This is why most production PostgreSQL setups add replication (becoming CP with synchronous replication or AP with async).

MySQL (single node)

Same as PostgreSQL — fully consistent and available as a single instance. MySQL Group Replication or InnoDB Cluster introduces distributed behavior where CAP tradeoffs apply.

What Happens During a Network Partition?

Let's walk through a concrete scenario to make this tangible:

Scenario: 3-node database cluster. Network between Node A and Nodes B+C fails.

┌─────────┐         ╳ NETWORK PARTITION ╳         ┌─────────┐
│ Node A  │ ←──── can't communicate ────→         │ Node B  │
│ (alone) │                                       │ Node C  │
└─────────┘                                       └─────────┘

User writes "balance = $500" to Node A.
User reads from Node B. What do they see?

CP System (e.g., MongoDB):
  → Node A realizes it's in the minority (1 of 3 nodes)
  → Node A stops accepting writes (returns error)
  → Nodes B+C elect a new primary, continue serving
  → User at Node A gets an error, user at Node B gets consistent data

AP System (e.g., Cassandra):
  → Node A accepts the write ($500)
  → Node B serves a read with the OLD value (stale!)
  → After partition heals, nodes sync: last write wins
  → Brief window of inconsistency, but no downtime

This is the fundamental tradeoff. In a banking app, serving a stale balance could mean allowing an overdraft — you want CP. In a social media feed, showing a post 2 seconds late is fine — you want AP.

Popular Databases Mapped to CAP

DatabaseCAP CategoryDuring PartitionNotes
PostgreSQLCA (single) / CP (replicated)Sync replication blocks; async may lose writesDefault single-node is CA; add replication for P
MySQLCA (single) / CP (Group Repl.)Group Replication requires majority quorumInnoDB Cluster enforces consistency
MongoDBCPMinority partition becomes read-only or unavailableReplica set with automatic failover
CassandraAP (default)All nodes accept reads/writes; sync laterTunable — QUORUM gives CP-like behavior
RedisAP (Cluster) / CP (Sentinel)Depends on configuration and failover modeAsync replication = possible data loss on failover
DynamoDBAP (default)Eventually consistent reads; always availableStrongly consistent reads available per-request
CockroachDBCPMinority ranges become unavailableSerializable isolation, Raft consensus

Important nuance: many databases let you tune the tradeoff per-query. Cassandra with QUORUM consistency behaves more like CP. DynamoDB with strongly-consistent reads sacrifices some availability. The CAP category is the default behavior.

CAP Theorem Limitations & PACELC

CAP is useful as a mental model, but it has real limitations that are worth understanding:

CAP is about partitions only

CAP only describes behavior during a network partition. It says nothing about normal operation. Most of the time your system isn't partitioned — and you're still making tradeoffs between latency and consistency that CAP doesn't address.

It's not binary

Real systems aren't purely CP or AP — they exist on a spectrum. Cassandra with QUORUM is "more CP" than with consistency level ONE. MongoDB with read preference secondaryPreferred is "more AP." The labels are simplifications.

Latency isn't captured

A system could be technically "consistent" but take 10 seconds to respond while waiting for all nodes to confirm. CAP doesn't distinguish between a fast response and a slow one — only whether you get a response at all.

PACELC Theorem — The Better Model

PACELC (proposed by Daniel Abadi in 2012) extends CAP to address normal operation:

PACELC: If (P)artition → choose (A)vailability or (C)onsistency
        Else (no partition) → choose (L)atency or (C)onsistency

Examples:
  DynamoDB:  PA/EL  — Available during partition, low latency normally
  Cassandra: PA/EL  — Same as DynamoDB (eventual consistency = fast reads)
  MongoDB:   PC/EC  — Consistent during partition AND during normal ops
  CockroachDB: PC/EC — Always strongly consistent (higher latency)
  PostgreSQL (async replica): PA/EL — fast reads from replica, eventual consistency

The "Else" part captures the daily tradeoff:
  → Do you wait for all replicas to confirm (consistent but slow)?
  → Or return after one node confirms (fast but potentially stale)?

PACELC is a more complete model because it addresses what happens 99.9% of the time (no partition) in addition to the rare partition case. If you're choosing a database, think about both: what happens during failure AND what happens during normal operation.

How Databases Actually Implement CAP Tradeoffs

Understanding the mechanisms behind CAP choices helps you configure your database correctly:

Consensus Protocols (CP Systems)

CP databases use consensus algorithms like Raft (CockroachDB, etcd) or Paxos to ensure all nodes agree on data before confirming a write. A write isn't acknowledged until a majority of nodes have it. This guarantees consistency but means writes fail if the majority is unreachable.

Eventual Consistency (AP Systems)

AP databases accept writes on any node and propagate changes asynchronously. Techniques include gossip protocols (Cassandra), anti-entropy repair, read repair, and hinted handoff. Conflicts are resolved using timestamps (last write wins), vector clocks, or CRDTs (Conflict-free Replicated Data Types).

Tunable Consistency

Some databases let you choose per-operation. Cassandra's consistency levels: ONE (fast, may be stale), QUORUM (majority must respond — CP-like), ALL (all nodes must respond — slowest, strongest). DynamoDB offers "eventually consistent" vs "strongly consistent" reads.

Quorum Mathematics

For strong consistency in a replicated system: W + R > N (where W = write acknowledgments, R = read acknowledgments, N = total replicas). If W=2, R=2, N=3: reads always see the latest write because the read and write sets overlap. This is how QUORUM works in Cassandra.

Cassandra Consistency Levels — A Practical Example (3 replicas)
═══════════════════════════════════════════════════════════════════

Level       Write to   Read from   Strong?   Speed     Availability
──────────  ─────────  ──────────  ────────  ────────  ──────────────
ONE         1 node     1 node      No        Fastest   Highest (AP)
QUORUM      2 nodes    2 nodes     Yes*      Medium    Medium (CP-ish)
ALL         3 nodes    3 nodes     Yes       Slowest   Lowest

* QUORUM is strong when W(quorum) + R(quorum) > N
  With N=3: W=2, R=2 → 2+2=4 > 3 ✓ (reads overlap with writes)

Recommendation:
- Social feeds, analytics: ONE (fast, eventual consistency is fine)
- User profiles, preferences: QUORUM (balance of speed and consistency)
- Financial data: ALL or use a CP database instead

When to Choose CP vs AP

The right choice depends entirely on your use case. Here's a practical framework:

Choose CP (Consistency) When...

Banking & financial transactions

A user's balance must be accurate. Serving a stale balance could allow overdrafts, double-spending, or incorrect transfers. Better to reject the request than give wrong data.

Inventory & booking systems

If there's 1 seat left on a flight, two users shouldn't both be able to book it. Strong consistency prevents overselling. Hotel bookings, concert tickets, limited stock items — all need CP.

User authentication & permissions

If a user's access is revoked, that must take effect immediately everywhere. Serving stale permission data could give a fired employee access to sensitive systems.

Leader election & coordination

Distributed locks, leader election, and configuration management require strong consistency. Two nodes thinking they're the leader simultaneously causes data corruption.

Choose AP (Availability) When...

Social media feeds & timelines

If a tweet appears 2 seconds late for some users, nobody notices. But if Twitter is "down" — everyone notices. Availability matters more than millisecond-perfect consistency here.

CDN and content delivery

CDN edge nodes serve cached content that might be slightly stale. That's fine — serving the page fast from a nearby node is more important than ensuring every user sees the absolute latest version simultaneously.

Analytics and metrics dashboards

Your dashboard showing 1,000,003 pageviews instead of 1,000,005 for a few seconds doesn't matter. The dashboard being unavailable when you need to diagnose a production issue does matter.

Shopping carts (before checkout)

A user adding items to their cart can tolerate brief inconsistencies. The cart eventually syncs. But the "add to cart" button being broken (unavailable) means lost revenue immediately.

CAP Theorem in Microservices Architecture

In a microservices world, CAP applies not just to your database but to inter-service communication. Each service boundary introduces potential partition scenarios:

Microservices CAP Scenario:
═══════════════════════════════════════

Order Service ──────╳──────── Inventory Service
     │               (network partition)        │
     │                                          │
User places order. Order Service can't reach Inventory Service.

CP Approach:
  → Reject the order (return error to user)
  → "Sorry, can't process right now"
  → No risk of overselling

AP Approach:
  → Accept the order optimistically
  → Check inventory when connection restores
  → Risk: might oversell, need compensation logic

Saga Pattern (practical AP):
  → Accept order provisionally
  → When network heals, confirm with Inventory
  → If out of stock, send cancellation email
  → Customer experience: "Order placed!" then maybe "Sorry, out of stock"

The saga pattern is how most real microservices handle this. Pure CP (reject everything when one service is down) makes your entire system as fragile as your weakest link. Pure AP (accept everything and deal with it later) requires robust compensation logic. Most teams land somewhere in between, making different choices for different operations.

Circuit breakers add AP behavior

When a downstream service fails, a circuit breaker returns a fallback response instead of failing the whole request. This is choosing availability over consistency — you serve a degraded but functional experience rather than an error page.

Event sourcing enables eventual consistency

Rather than synchronous inter-service calls, services publish events to a message broker (Kafka, SQS). Other services consume events asynchronously. The system is eventually consistent but highly available — services don't block on each other.

Different consistency per operation

Your checkout flow might be CP (strong consistency for payment + inventory), while your product recommendations are AP (stale data is fine). Design each operation's consistency requirements independently.

Common Misconceptions About CAP

❌ "You pick 2 out of 3 when designing your system"

You don't choose at design time — you choose during a partition. When there's no partition (most of the time), you can have both consistency and availability. The tradeoff only kicks in during network failures.

❌ "CA databases exist in distributed systems"

In a distributed system, network partitions are inevitable. You can't opt out of P. A "CA" system is just a single-node database that hasn't been distributed yet. The moment you add replication, you must choose C or A during partitions.

❌ "CAP means you sacrifice one property entirely"

AP systems aren't completely inconsistent — they're eventually consistent. The inconsistency window is usually milliseconds to seconds. CP systems aren't completely unavailable — only nodes in the minority partition become unavailable. It's a matter of degree.

❌ "My whole system must be CP or AP"

Different parts of your system can make different tradeoffs. Your payment processing might be CP (MongoDB) while your activity feed is AP (Cassandra). Even within one database, you can have different consistency levels per query.

❌ "Network partitions are rare so CAP doesn't matter"

Network issues are more common than you think — cloud provider network blips, DNS failures, misconfigured firewalls, cable cuts, overloaded switches. Google reported network partition events hundreds of times per year across their infrastructure. Plan for it.

Practical CAP Decision Guide for Your Stack

Here's how to think about CAP when building different types of applications:

Application TypeRecommendedDatabase ChoiceReasoning
E-commerce (checkout)CPPostgreSQL, CockroachDBCan't oversell inventory or double-charge
E-commerce (catalog)APDynamoDB, ElasticsearchSlightly stale price is fine; catalog must be browsable
Chat / messagingAPCassandra, ScyllaDBMessages arriving slightly out of order is okay; being unable to send isn't
Banking / fintechCPPostgreSQL, CockroachDBAccount balances must be exact; regulatory compliance demands it
IoT / sensor dataAPTimescaleDB, InfluxDBHigh write throughput matters more than perfect read consistency
User sessions / authCPRedis (Sentinel), PostgreSQLStale auth data = security vulnerability
Content / CMSAPMongoDB, DynamoDBBlog post appearing 2 seconds late is invisible to users

Frequently Asked Questions

What is the CAP theorem?

The CAP theorem states that a distributed database can only guarantee two out of three properties simultaneously: Consistency (every read gets the most recent write), Availability (every request gets a response), and Partition Tolerance (the system works even when network communication between nodes fails). Since network partitions are unavoidable, you're really choosing between consistency and availability.

Why can't you have all three (C, A, and P)?

When a network partition happens (nodes can't communicate), the system must make a choice: either stop responding to maintain consistency (CP) or continue responding with potentially stale data to maintain availability (AP). You can't guarantee both fresh data AND responses when nodes are disconnected.

Is MongoDB CP or AP?

MongoDB is CP (Consistency + Partition Tolerance) by default. During a network partition, if the primary becomes unreachable, the replica set elects a new primary. Writes to the old primary are rolled back. MongoDB prioritizes consistency — it won't serve stale reads from the primary.

Is Cassandra CP or AP?

Cassandra is AP (Availability + Partition Tolerance) by default. It continues accepting reads and writes even during network partitions, using eventual consistency to synchronize data later. You can tune consistency per-query (QUORUM, ALL) to get stronger guarantees.

Where does PostgreSQL fit in CAP?

A single-node PostgreSQL is CA (Consistent + Available) — it's always consistent and always available, but it's not partition tolerant because it's a single machine. Once you add replication across nodes, you must choose between CP and AP depending on your replication configuration.

What is eventual consistency?

Eventual consistency means that if no new updates are made, all nodes will eventually have the same data — but there's no guarantee when. A read might return stale data for a short period after a write. AP systems like Cassandra and DynamoDB use this model.

What is the PACELC theorem?

PACELC extends CAP by addressing what happens when there's NO partition. It says: if there's a Partition, choose Availability or Consistency. Else (no partition), choose Latency or Consistency. This captures the real-world tradeoff better — even without failures, you're choosing between fast reads and consistent reads.

When should I choose CP vs AP?

Choose CP when incorrect data is worse than no data — banking, inventory management, booking systems. Choose AP when stale data is acceptable but downtime isn't — social media feeds, analytics dashboards, content delivery, DNS. Most systems need different guarantees for different operations.

Related Articles & Tools

Conclusion

CAP theorem boils down to one question: when your distributed database nodes can't talk to each other, do you want them to stop responding (consistency) or keep responding with potentially stale data (availability)? Neither answer is universally correct — it depends on what you're building.

For financial data, inventory counts, and anything where "wrong" is worse than "unavailable," choose CP (MongoDB, CockroachDB). For social feeds, analytics, and anything where "down" is worse than "slightly stale," choose AP (Cassandra, DynamoDB).

And remember: most systems aren't purely one or the other. Your payment service might be CP while your notification service is AP. The best architectures use the right consistency model for each piece of data based on its actual requirements.