---
title: "04 — Consistency Patterns: Strong, Weak, and Eventual"
uid: consistency-patterns
tags: ["distributed-systems", "consistency", "replication", "roadmap:system-design", "system-design"]
excerpt: "A consistency pattern is a contract about how soon after a write the next read sees it — and the cost climbs steeply with the strength of the guarantee. The whole map is three contracts."
date: 2026-08-13T03:27:34+0000
source: https://www.aveshina.my.id/en/blog/consistency-patterns
---

"Just let the database sort it" was my consistency strategy, which made every surprising read feel like a bug. Writing it down turned a vague intuition into a contract I can reason about: **a consistency pattern is a guarantee about how soon after a write the next read will see it — and the cost climbs steeply with the strength of the guarantee.** [1] The whole map is just three contracts.

The framing that clicked is that "consistency" is not a single dial. It is a _spectrum of promises_ the store makes to readers about visibility of writes. Strong consistency is the strictest promise (instant, everywhere), weak consistency is the loosest (no promise at all), and eventual consistency sits in the middle as the practical default for distributed systems that need to stay available [1]. Once I saw the three as points on one spectrum, picking one became a cost/benefit decision instead of a guess.

## The three contracts

The roadmap collapses the field to three patterns, and that is genuinely most of what I need day to day [1]:

```figure
<svg viewBox="0 0 740 290" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="Three consistency lanes. Each lane has a write (W) on the left and three replica reads (R1 R2 R3) on the right. Strong: all three reads turn green immediately after the write. Eventual: the reads turn green one after another over time. Weak: no predictable timing — some reads may not see the write at all.">
  <defs>
    <marker id="carrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">

    <!-- STRONG -->
    <text x="20" y="40" font-size="13" font-weight="700" fill="#052e16">Strong</text>
    <text x="20" y="58" font-size="10" fill="#64748b">synchronous · all replicas</text>
    <rect x="100" y="28" width="36" height="32" rx="6" fill="#dcfce7" stroke="#16a34a" stroke-width="1.5"/>
    <text x="118" y="49" font-size="11" font-weight="700" fill="#052e16" text-anchor="middle">W</text>
    <g>
      <rect x="560" y="20" width="44" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
      <text x="582" y="35" font-size="10" font-weight="700" fill="#052e16" text-anchor="middle">R1 ✓</text>
      <rect x="612" y="20" width="44" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
      <text x="634" y="35" font-size="10" font-weight="700" fill="#052e16" text-anchor="middle">R2 ✓</text>
      <rect x="664" y="20" width="44" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
      <text x="686" y="35" font-size="10" font-weight="700" fill="#052e16" text-anchor="middle">R3 ✓</text>
    </g>
    <path d="M136,44 C300,44 420,32 558,32" fill="none" stroke="#16a34a" stroke-width="1.5" marker-end="url(#carrow)"/>
    <text x="346" y="24" font-size="10" fill="#052e16" text-anchor="middle" font-style="italic">immediate, all replicas</text>

    <!-- EVENTUAL -->
    <text x="20" y="140" font-size="13" font-weight="700" fill="#1e1b4b">Eventual</text>
    <text x="20" y="158" font-size="10" fill="#64748b">async · converges over time</text>
    <rect x="100" y="128" width="36" height="32" rx="6" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="118" y="149" font-size="11" font-weight="700" fill="#1e1b4b" text-anchor="middle">W</text>
    <g>
      <rect x="560" y="120" width="44" height="22" rx="4" fill="#dcfce7" stroke="#16a34a" stroke-width="1.2"/>
      <text x="582" y="135" font-size="10" font-weight="700" fill="#052e16" text-anchor="middle">R1 ✓</text>
      <rect x="612" y="120" width="44" height="22" rx="4" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.2"/>
      <text x="634" y="135" font-size="10" font-weight="700" fill="#422006" text-anchor="middle">R2 …</text>
      <rect x="664" y="120" width="44" height="22" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1.2"/>
      <text x="686" y="135" font-size="10" font-weight="700" fill="#7f1d1d" text-anchor="middle">R3 ✗</text>
    </g>
    <path d="M136,144 C300,144 420,132 558,132" fill="none" stroke="#6366f1" stroke-width="1.5" marker-end="url(#carrow)"/>
    <text x="346" y="124" font-size="10" fill="#1e1b4b" text-anchor="middle" font-style="italic">replicas catch up over time</text>

    <!-- WEAK -->
    <text x="20" y="240" font-size="13" font-weight="700" fill="#7f1d1d">Weak</text>
    <text x="20" y="258" font-size="10" fill="#64748b">no guarantee</text>
    <rect x="100" y="228" width="36" height="32" rx="6" fill="#fee2e2" stroke="#dc2626" stroke-width="1.5"/>
    <text x="118" y="249" font-size="11" font-weight="700" fill="#7f1d1d" text-anchor="middle">W</text>
    <g>
      <rect x="560" y="220" width="44" height="22" rx="4" fill="#fef9c3" stroke="#ca8a04" stroke-width="1.2"/>
      <text x="582" y="235" font-size="10" font-weight="700" fill="#422006" text-anchor="middle">R1 ?</text>
      <rect x="612" y="220" width="44" height="22" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1.2"/>
      <text x="634" y="235" font-size="10" font-weight="700" fill="#7f1d1d" text-anchor="middle">R2 ?</text>
      <rect x="664" y="220" width="44" height="22" rx="4" fill="#fee2e2" stroke="#dc2626" stroke-width="1.2"/>
      <text x="686" y="235" font-size="10" font-weight="700" fill="#7f1d1d" text-anchor="middle">R3 ?</text>
    </g>
    <path d="M136,244 C300,244 420,232 558,232" fill="none" stroke="#dc2626" stroke-width="1.5" stroke-dasharray="5 4" marker-end="url(#carrow)"/>
    <text x="346" y="224" font-size="10" fill="#7f1d1d" text-anchor="middle" font-style="italic">read may or may not see the write</text>
  </g>
</svg>
```

- **Strong consistency.** After a write, any subsequent read — from any replica — immediately reflects it. The data is replicated synchronously, so every copy is updated at the same time before the write is acknowledged [1]. Cost: the write blocks until all replicas agree, so latency is higher and availability drops if a replica is unreachable. This is the CP side of CAP.
- **Weak consistency.** After a write, a subsequent read is _not_ guaranteed to reflect it. The read may or may not see the recent change [1]. This is the loosest contract — best effort, no promises. It is rarely chosen explicitly; it is the default of systems that make no consistency claim at all.
- **Eventual consistency.** A specific, weaker form of strong consistency (and the most common flavor of weak). After a write, it will _eventually_ be visible to any subsequent read — the data is replicated asynchronously, so all copies converge once propagation finishes [1]. Cost: during the convergence window, reads can be stale, but writes are fast and the system stays available. This is the AP side of CAP, and the workhorse of real-world distributed stores.

## The cost ladder

The way of thinking that made these click is a cost ladder. Going up the ladder — weak → eventual → strong — buys stronger read guarantees and pays for them with write latency and reduced availability under failures:

- **Weak** costs nothing in latency but promises nothing.
- **Eventual** costs a convergence window (milliseconds to seconds) in exchange for fast writes and high availability.
- **Strong** costs synchronous coordination on every write, which is why truly strong-consistency stores are slower and harder to keep up under partition.

## How I use this

I treat the choice as a per-data-type question, same as the CAP decision it underpins. For anything where a stale read causes real harm — a balance, a stock level, an auth token revocation — I pay for strong consistency and accept the slower writes. For everything else — feeds, counts, search indexes, denormalized read models — eventual consistency is the default, because fast writes and uptime matter more than perfect freshness, and a few seconds of staleness is invisible to the user. The discipline is to stop defaulting to "whatever the database does" and instead name the contract each dataset actually needs.

## References

[1] cs.fyi, "Consistency patterns in distributed systems (weak, strong, eventual)," 2021. [Online]. Available: [https://cs.fyi/guide/consistency-patterns-week-strong-eventual/](https://cs.fyi/guide/consistency-patterns-week-strong-eventual/)

[2] D. Martin, "Eventual consistency," system-design-primer (open source), 2024. [Online]. Available: [https://github.com/donnemartin/system-design-primer#eventual-consistency](https://github.com/donnemartin/system-design-primer#eventual-consistency)

[3] "CAP theorem revisited," robertgreiner.com, 2014. [Online]. Available: [https://robertgreiner.com/cap-theorem-revisited/](https://robertgreiner.com/cap-theorem-revisited/)

[4] "A plain english introduction to CAP theorem," ksat.me. [Online]. Available: [http://ksat.me/a-plain-english-introduction-to-cap-theorem](http://ksat.me/a-plain-english-introduction-to-cap-theorem)

```quiz
Q: After a write, a read is guaranteed to immediately see it on every replica. That is…
- strong consistency
- eventual consistency
correct: 0
explain: Strong consistency replicates synchronously, so every copy reflects the write before it is acknowledged. Eventual consistency only promises convergence over time.

Q: Eventual consistency is best described as…
- a specific (and common) form of weak consistency
- a synonym for strong consistency
correct: 0
explain: Eventual consistency is a flavor of weak consistency: it makes a limited promise — writes become visible eventually — without guaranteeing immediate visibility.

Q: Moving up the cost ladder from weak → eventual → strong, you mostly trade…
- lower write latency for weaker read guarantees
- stronger read guarantees for higher write latency and reduced availability
correct: 1
explain: Stronger consistency needs synchronous coordination, which slows writes and hurts availability under failures. Weaker consistency buys fast writes and high availability at the cost of stale reads.

Q: A social-media like count most naturally fits…
- strong consistency
- eventual consistency
correct: 1
explain: A like count a few seconds stale is harmless, and fast writes plus uptime matter more. Feeds and counts are classic eventual-consistency data.
```
