20% off StaffSignal for a limited time →
StaffSignal Brand Icon
StaffSignal
Foundation — Study Guide23 min read

Consistency Models & Partition Behavior

"Eventual consistency" is not a single thing — it's a spectrum, and the right point on it is a business decision. Strong, causal, read-your-writes, monotonic, eventual — with per-operation tuning. How Google Spanner achieves global strong consistency, why DynamoDB defaults to eventual, and how LinkedIn tunes consistency per-operation in production.

Why This Matters

Every distributed system stores copies of data in multiple places — replicas across nodes, regions, or availability zones. The moment you have more than one copy, you face a question that defines your entire architecture: when one copy changes, how quickly and reliably do the other copies reflect that change?

The answer to this question is your consistency model. It is not a technical setting you configure once and forget. It is a product decision that determines whether users see stale prices, whether bank balances can go negative, and whether collaborative editors lose each other's keystrokes.

Consistency models appear in every system design interview because they expose the candidate's ability to reason about tradeoffs rather than reach for defaults. The question is never "which consistency model is best?" — it is "which consistency model fits this operation, for this user, at this cost?" Staff engineers answer per-operation. Seniors answer per-system. That difference is the calibration signal interviewers look for.

The 60-Second Version

  • CAP is not "choose 2 of 3." Partitions happen whether you like it or not. During a partition, you choose between availability and consistency. That is the only choice.
  • The real question is what you do when there is no partition. PACELC extends CAP: without a partition, the daily tradeoff is latency vs. consistency — and that tradeoff runs on every single request.
  • "Eventually consistent" without a bounded staleness number is not a design — it is a hope. Staff engineers quantify: "replicas converge within 200ms in-region, and we alert when p99 exceeds it."
  • Consistency is chosen per operation, not per system. Your payment path can be linearizable while your feed is eventually consistent. Saying "our system is AP" is a senior-level answer. Saying "our payment path is CP, our feed is AP, and profile edits guarantee read-your-writes" is a Staff-level answer.
  • Read-your-writes is the minimum bar for any user-facing system. Users must see their own mutations immediately. Violating this feels like data loss, even when no data was lost.
  • Linearizability costs 100–300ms per operation across regions. Most operations don't need it. Over-applying it destroys latency for no user-visible benefit. Under-applying it causes data corruption in financial and inventory operations.

How Consistency Works

The Core Problem: Multiple Copies

A single database on a single server has no consistency problem. Every read sees the latest write. The data lives in one place.

The moment you add a second copy — a read replica, a cache, a replica in another region — you have two versions of the truth. A write lands on one copy. Until it propagates to the other copy, the two copies disagree. The time they disagree is the replication lag, and everything about consistency models is about how you manage that disagreement.

Consider a simple example: a user updates their display name from "Alice" to "Alicia."

  1. The write lands on the primary database in us-east.
  2. The primary begins replicating to a replica in eu-west.
  3. Replication takes 120ms (cross-Atlantic network latency).
  4. During those 120ms, a reader in Europe queries the eu-west replica and sees "Alice" — the old name.

Is this a bug? It depends on who is reading. If Alice herself refreshes her profile page and still sees "Alice" after clicking save, it feels like data loss. If Alice's colleague in London sees "Alice" for 120ms before the update arrives, nobody notices.

This distinction — who is reading, and what guarantee do they need — is the foundation of consistency model selection.

Replication: Synchronous vs. Asynchronous

The fundamental mechanism behind consistency is how replicas receive updates.

Synchronous replication: The write is not acknowledged to the client until all (or a quorum of) replicas have confirmed they received it. Every read from any replica sees the latest write. The cost is latency — every write waits for the slowest replica.

Asynchronous replication: The write is acknowledged as soon as the primary stores it. Replicas receive the update in the background. Reads from replicas may return stale data. The benefit is low write latency and high availability.

Most production systems use asynchronous replication for performance and introduce consistency guarantees selectively for operations that need them.

The Consistency Spectrum

Consistency is not binary (consistent vs. inconsistent). It is a spectrum of guarantees, each with increasing strength and increasing cost.

Rendering diagram...

Eventual Consistency

Guarantee: If no new writes occur, all replicas will eventually converge to the same value.

What "eventually" means in practice: Same-region replicas typically converge within 10–100ms. Cross-region replicas converge within 100–500ms. But "eventually" has no upper bound unless you define one.

How it works: Writes go to the primary. The primary asynchronously ships changes to replicas. Replicas apply changes when they arrive. During the replication window, different replicas may return different values for the same key.

Where it is appropriate:

  • Activity feeds ("Alice liked a photo" — 500ms delay is invisible)
  • View counters (approximate counts are acceptable)
  • Recommendation engines (stale features affect relevance marginally)
  • Analytics dashboards (seconds-old data is fine)

Where it breaks:

  • A user saves their profile and immediately reads it back. If the read hits a stale replica, they see their old data. This feels like data loss.
  • Two users simultaneously edit the same document. Without ordering guarantees, edits can be silently lost.

The Staff-level framing: "Eventually consistent" without a number is not a design — it is a hope. Always quantify: "replicas converge within 200ms in-region, and we set an SLO alerting at p99 > 500ms."

Monotonic Reads

Guarantee: Once a client sees version N of a value, it will never see a version older than N on subsequent reads.

The problem it solves: Under eventual consistency with multiple replicas, a client can "go back in time." Request 1 hits a recently-updated replica and sees version 5. Request 2 hits a lagging replica and sees version 3. From the user's perspective, data disappeared.

How it is implemented: Route all reads from the same client to the same replica (sticky sessions). As long as the client consistently reads from one replica, it sees a monotonically advancing version.

Where it matters:

  • Dashboard statistics (numbers should not jump backward)
  • Browsing history (items should not disappear and reappear)
  • Scroll position in a feed (content should not reshuffle)

Cost: Sticky sessions reduce load-balancing flexibility. If the sticky replica goes down, the client must be re-routed, potentially seeing an older version during the transition.

Read-Your-Writes (Read-After-Write)

Guarantee: A client always sees the result of its own writes immediately, regardless of which replica serves the read.

The problem it solves: A user updates their profile name. They refresh the page. If the read goes to a stale replica, they see the old name. The user thinks the save failed. They try again. They get confused.

How it is implemented:

# Pseudocode for read-your-writes routing
on_write(user_id, data):
    primary.write(user_id, data)
    last_write_time[user_id] = now()

on_read(user_id, requesting_user):
    # If the requesting user just wrote, route to primary
    if requesting_user == user_id:
        if now() - last_write_time[user_id] < 5_seconds:
            return primary.read(user_id)

    # Otherwise, any replica is fine
    return any_replica.read(user_id)

The writing user is routed to the primary for a brief window (typically 5 seconds) after their write. Other users continue reading from replicas, tolerating bounded staleness.

Where it is the minimum bar:

  • Profile edits (user must see their own changes)
  • Shopping cart updates (items must appear immediately after adding)
  • Settings changes (toggling dark mode must take effect now)
  • Any form submission where the user expects to see the result

Cost: Slightly higher read latency for the writing user during the routing window. Minimal impact on the overall system.

Causal Consistency

Guarantee: If event A caused event B, every replica sees A before B. Events that are causally unrelated can appear in any order.

The problem it solves: Alice posts a message. Bob replies to Alice's message. Under eventual consistency, some replicas might show Bob's reply before Alice's original message — a visible ordering violation. Causal consistency ensures that if Bob's reply depends on Alice's message, Alice's message is always visible first.

How it is implemented: Each operation carries a version vector or hybrid logical clock that tracks causal dependencies. Before applying an operation, a replica checks that all causal predecessors have been applied.

Where it matters:

  • Social media comments (replies must appear after the post they respond to)
  • Collaborative documents (edits that reference previous edits must be ordered)
  • Chat systems (messages in a thread must appear in causal order)

Cost: Version vectors add metadata to every operation. The replica must buffer and reorder operations that arrive out of causal order. This is more expensive than eventual consistency but significantly cheaper than linearizability because causally unrelated operations can proceed independently.

Linearizability (Strong Consistency)

Guarantee: Every read returns the value of the most recent write, globally. All operations appear to execute in a single, total order, as if there is one copy of the data.

The problem it solves: Multiple clients must agree on a single, globally consistent value. If two clients read an inventory count at the same time, they both see the same number. If one of them buys the last item, the next read by anyone sees the updated count.

How it is implemented: Quorum reads and writes (W + R > N) or consensus protocols (Raft, Paxos). Every write must be acknowledged by a majority of replicas before it is visible. Every read must check with a majority to ensure it sees the latest write.

Where it is required:

  • Account balances (stale reads lead to overdrafts)
  • Inventory counts for the last few items (overselling)
  • Lock acquisition (two clients must not both believe they hold the lock)
  • Leader election (two nodes must not both believe they are the leader)

Cost: This is the most expensive consistency model. Every operation requires network round-trips to a quorum of replicas. Cross-region linearizability adds 100–300ms per operation due to wide-area network latency. At global scale, this latency is often unacceptable for most operations, which is why linearizability is applied selectively.

CAP and PACELC: The Real Framework

CAP Theorem

CAP states that during a network partition, a distributed system must choose between:

  • Consistency (C): Every read returns the latest write or an error.
  • Availability (A): Every request receives a non-error response, even if it may be stale.

Partitions (P) are not optional — they happen regardless of your design. So the real choice is: during a partition, do you reject requests (choose C) or serve potentially stale data (choose A)?

The common mistake is treating CAP as "choose 2 of 3." You cannot "choose" to avoid partitions. The choice is only between C and A during a partition.

PACELC: The Daily Tradeoff

CAP only describes behavior during partitions — which are rare. PACELC extends the model to cover normal operation:

  • During a partition: Choose between consistency and availability (same as CAP)
  • Else (normal operation): Choose between latency and consistency

The PACELC insight is that the tradeoff you make every day — on every request — is latency vs. consistency. Strong consistency requires quorum round-trips, adding latency. Weaker consistency models allow faster local reads from replicas.

SystemDuring PartitionNormal Operation
DynamoDB (default)Availability over ConsistencyLatency over Consistency
PostgreSQL (sync replica)Consistency over AvailabilityConsistency over Latency
Cassandra (tunable)Configurable per queryConfigurable per query

Staff engineers frame their designs using PACELC, not CAP, because PACELC describes the tradeoff that actually runs in production every second — not just during rare failure events.

Per-Operation Consistency

The most important Staff-level insight is that consistency is chosen per operation, not per system. A single application makes different consistency choices for different operations:

OperationConsistency ModelWhyImplementation
Check account balanceLinearizableStale balance → overdraftQuorum read from primary
Display friend's postEventual (bounded)500ms staleness is invisibleRead from nearest replica
Add item to cartRead-your-writesUser must see their own cartRoute to primary for 5s post-write
Update shared documentCausalEdits must respect happens-beforeVersion vectors on operations
Show "like" countEventualApproximate counts are acceptableRead from any replica
Transfer money between accountsLinearizableDouble-spend preventionConsensus-based write
Display notification countEventual±1 notification is invisibleRead from local replica

This is the design pattern that interviewers look for at Staff level: not "our system is AP" but "our payment path is linearizable, our feed is eventually consistent with bounded staleness, and profile edits guarantee read-your-writes for the author."

Implementation Patterns

Quorum Configuration

The standard quorum formula for strong consistency:

# N = total replicas, W = write quorum, R = read quorum
# For strong consistency: W + R > N

# Classic configuration (N=3)
W=2, R=2    # Strong reads, tolerates 1 node failure

# Write-optimized (N=3)
W=1, R=3    # Fast writes, slow reads (must check all replicas)

# Read-optimized (N=3)
W=3, R=1    # Slow writes (all must confirm), fast reads (any replica is current)

The tradeoff: increasing W makes writes slower but reads faster (fewer replicas to check). Increasing R makes reads slower but writes faster.

Read-Your-Writes Routing

# Route the writing user to the primary for a brief window
ROUTING_WINDOW = 5  # seconds

on_read(key, user_id):
    last_write = get_last_write_time(user_id, key)

    if last_write and (now() - last_write) < ROUTING_WINDOW:
        return primary.read(key)     # strong read for the writer

    return nearest_replica.read(key)  # eventual for everyone else

This gives the writing user immediate consistency at minimal cost. The 5-second window is chosen because same-region replication typically completes in under 100ms — 5 seconds provides a comfortable margin.

Conflict Resolution Strategies

When two replicas accept conflicting writes during a partition (or during normal async replication), you need a resolution strategy:

StrategyHow It WorksData Loss RiskUse Case
Last-Writer-Wins (LWW)Timestamp determines winner; other write is discardedHigh — silently drops a writeSimple key-value stores, session data
CRDTsData structures that merge deterministically without coordinationNone — all operations are preservedCounters, sets, registers for collaborative apps
Application-level mergeCustom logic resolves conflicts based on business rulesDepends on implementationShopping carts, document merging
Reject conflicting writesDeny writes during partition; wait for consistencyNone — but reduced availabilityFinancial transactions, inventory

The Numbers in Context

NumberValueWhat It Means for Your Design
Same-region async replication lag10–100msMost reads from replicas are fresh enough for eventual consistency. Read-your-writes routing window of 5s provides a large safety margin.
Cross-region async replication lag100–500msGlobally distributed reads will see stale data for up to half a second. Users rarely notice, but inventory and financial operations cannot tolerate this.
Quorum formulaW + R > NWith N=3, W=2, R=2 is the standard for strong consistency. Dropping to R=1 trades consistency for tail-latency — acceptable for feeds, not for payments.
Raft/Paxos commit latency1–2 RTTs to leader commitIn-region: 1–2ms. Cross-region: 100–300ms. This is why linearizability is expensive at global scale.
Bounded staleness SLO200ms–1sDefine this as a measurable SLO, not a hope. Alert when p99 replication lag exceeds your bound.
Cross-region quorum write300ms+This is the cost of linearizability across regions. Most operations do not need it. Apply selectively.

How This Shows Up in Interviews

Scenario 1: "Design a multi-region system with low read latency"

The interviewer is testing whether you can articulate the PACELC tradeoff. The answer: "We use async replication to local read replicas for sub-100ms reads. During normal operation, we trade consistency for latency on reads. Writes route to the home region for the data. The writing user gets read-your-writes via primary routing for 5 seconds post-write. Other users tolerate bounded staleness of 500ms."

Scenario 2: "Two users buy the last item simultaneously" (Full Walkthrough)

This tests whether you know when linearizability is required and how to implement it without over-applying it.

Step 1 — Identify which operations need which consistency. "There are two read paths here: the product page showing 'In Stock' (browsing) and the actual purchase (checkout). Browsing is read-heavy and can tolerate bounded staleness — showing '3 in stock' when the real count is 2 is invisible to users. The purchase itself is a write that must be linearizable — we cannot allow two users to both decrement inventory from 1 to 0."

Step 2 — Design the browse path (eventual consistency). "Product pages read inventory from the nearest replica. Cross-region lag means Tokyo might show '1 in stock' 200ms after Virginia bought it. That's acceptable — the product page is a hint, not a guarantee. We set a bounded staleness SLO of 500ms and display 'In Stock' rather than exact counts when inventory is above a threshold."

Step 3 — Design the purchase path (linearizability). "The checkout operation routes to the inventory's home region — the primary that owns the source of truth. We use a conditional update: UPDATE inventory SET count = count - 1 WHERE product_id = X AND count > 0. This is a compare-and-swap — only one concurrent request succeeds. If the update affects zero rows, we return 'Sorry, this item just sold out.'"

Step 4 — Handle the edge case: Tokyo vs Virginia. "A Tokyo user clicks 'Buy' when their local replica shows 1 in stock. The request routes to the primary in Virginia. Round-trip is ~150ms. If a Virginia user already bought the last one, Tokyo gets an immediate 'sold out' error — not a silent oversell. The 150ms purchase latency is acceptable for a checkout operation."

Step 5 — Frame as a product tradeoff. "We trade slightly stale product pages for sub-100ms global browse latency. The only strongly-consistent operation is the purchase itself. This is a PACELC decision: during normal operation, we choose latency over consistency for reads, and consistency over latency for writes."

Why this is a Staff answer: It applies different consistency models to different operations within the same flow, quantifies the latency costs, and frames the technical decision as a product tradeoff — not a technical preference.

Scenario 3: "How does your system behave during a network partition?"

This tests CAP understanding. The answer: "It depends on the operation. Our payment path rejects writes during a partition — we choose consistency. Our content feed continues serving from local replicas — we choose availability. We do not make a single CAP choice for the whole system."

Scenario 4: "Users are complaining they don't see their own changes"

This tests read-your-writes. The answer: "We route the writing user's reads to the primary for 5 seconds post-mutation. If the complaint persists, check whether the routing window is too short (replication lag spikes above 5s) or whether the client is load-balanced across regions and hitting a replica in a different region than the primary."

In the Wild

Google Spanner: Linearizability at Global Scale (TrueTime)

Most systems avoid global linearizability because it requires cross-region coordination that adds 100–300ms per operation. Google Spanner achieves it using TrueTime — GPS-synchronized atomic clocks in every data center that bound clock uncertainty to under 7ms. When Spanner commits a transaction, it waits for the uncertainty window to pass before making the write visible. This means every read, from any region, is guaranteed to see the latest committed write.

The Staff-level insight: Spanner pays the cost of linearizability (the wait time) on every write, not every read. Reads are fast because they can trust the timestamp ordering. This is a hardware-assisted consistency model — Google built custom infrastructure to make a consistency guarantee that would otherwise be impractical at global scale. In an interview, reference Spanner when the interviewer pushes "can you make this globally consistent?" — it's the existence proof, and explaining why most systems can't replicate it (no access to TrueTime) demonstrates depth.

Amazon DynamoDB: Per-Request Consistency Tuning

DynamoDB lets you choose consistency per read request, not per table. A GetItem call with ConsistentRead=false (the default) reads from any replica — fast but potentially stale. Setting ConsistentRead=true routes to the leader, guaranteeing the latest value at the cost of higher latency and double the read capacity units.

The Staff-level insight: This is per-operation consistency in a managed service. DynamoDB doesn't force you to choose AP or CP for the whole table — you make the choice on every request. In an interview, this is the concrete example you cite when explaining per-operation consistency: "DynamoDB does exactly this — consistent reads for checkout, eventual reads for browsing."

LinkedIn: Causal Consistency for the Feed

LinkedIn's feed system uses causal consistency to ensure that if you post an update and then comment on it, every reader sees the post before the comment. They track causal dependencies using vector clocks attached to each operation. Replicas buffer and reorder operations to preserve causal ordering before making them visible.

The Staff-level insight: LinkedIn chose causal over linearizable because the feed doesn't need global total ordering — it needs dependency ordering. Two unrelated posts can appear in any order. But a reply must appear after the post it references. Causal consistency provides this guarantee at significantly lower cost than linearizability, because causally unrelated operations don't wait for each other.


Staff Calibration

What Staff Engineers Say (That Seniors Don't)

ConceptSenior ResponseStaff Response
CAP theorem"We pick AP or CP""Partitions are a given. The interesting design is the PACELC tradeoff we make on every non-partition request — latency vs. consistency."
Eventual consistency"Replicas sync up eventually""Our async replicas lag 10–100ms in-region. We set a bounded staleness SLO of 200ms and alert when p99 exceeds it."
Quorum writes"We write to a majority""W + R > N gives us strong reads. With N=3, W=2, R=2 is standard. Dropping to R=1 trades consistency for tail-latency — acceptable for the activity feed, not for payments."
Read-your-writes"We can use sticky sessions""We route the writing user to the primary for 5s post-mutation, then fall back to replicas. Other users tolerate bounded staleness."
Cross-region replication"We replicate across regions""100–500ms cross-region lag means we offer causal consistency globally and linearizability only within the home region. Region failover surfaces a staleness window we size into the RPO budget."

Common Interview Traps

  • Treating CAP as a permanent architecture label. Systems make different consistency choices per operation, not one global setting. A payments path can be CP while a recommendations feed is AP within the same system.
  • Ignoring the "no partition" case. Partitions are rare. Interviewers want to hear how you handle the latency-consistency tradeoff that runs on every normal request.
  • Saying "eventually consistent" without quantifying staleness. Always attach a number. "How eventual?" is the follow-up that separates Staff answers from Senior ones.
  • Forgetting read-your-writes. Proposing an async-replicated system without explaining how the writing user sees their own data is a red flag at Staff level.
  • Applying linearizability everywhere "to be safe." Linearizability at global scale means quorum writes across regions — 300ms+ per write. Most operations don't need it. Over-applying it destroys latency for no user-visible benefit.
  • Confusing "consistent" with "correct." Eventual consistency is not inconsistency — it is a guarantee that replicas converge. The question is how fast and what happens during the convergence window.
  • Ignoring conflict resolution. If two regions accept conflicting writes during a partition, you need a resolution strategy: last-writer-wins (data loss risk), CRDTs (restricted operations), or manual merge (operational cost).

Practice Drill

Staff-Caliber Answer Shape
Expand
  1. Accept the staleness for reads. Cross-region replication lag (100-500ms) means Tokyo sees a stale inventory count. This is the PACELC tradeoff: during normal operation, we choose latency over consistency for reads.
  2. Enforce consistency on writes. The purchase operation routes to the inventory's home region (where the source of truth lives). This adds 150ms for a Tokyo user, but it prevents overselling.
  3. Optimistic UI with server validation. Show "in stock" based on local replica. When user clicks "buy," the request goes to the home region. If inventory is gone, return a clear error: "Sorry, this item just sold out." This is a graceful degradation, not a bug.
  4. Bounded staleness SLO. Set an SLO: replicas within 500ms of primary. Alert when lag exceeds this. Users see slightly stale counts, but the window is small enough that oversell conflicts are rare.

The Staff move: Frame the answer as a product tradeoff: "We trade slightly stale product pages for sub-100ms global reads. The only strongly-consistent operation is the purchase itself."

Where This Appears

These playbooks apply consistency model foundations to complete system design problems with full Staff-level walkthroughs, evaluator-grade rubrics, and practice drills.

  • Data Consistency & Replication — Replication topology design, RPO/RTO as business decisions, cross-region consistency strategies, and the operational reality of failover staleness windows
  • Distributed Consensus — When to use consensus vs when to avoid it, Raft/Paxos operational costs, minimizing the consensus domain, and why most systems should not build their own consensus layer
  • Distributed Caching — Cache consistency as a specific instance of the consistency spectrum, invalidation pipelines as eventual consistency mechanisms, and multi-region cache coherence
  • Collaborative Editing — CRDTs vs OT as conflict resolution strategies, causal consistency in real-time collaboration, and why last-writer-wins destroys user trust in shared documents

Related Technologies: PostgreSQL · Cassandra · DynamoDB · ZooKeeper/etcd

This is one of 9 foundation guides. The full library also includes deep-dive system design playbooks with evaluator-grade breakdowns, practice drills, and failure-mode analysis. Explore the full library