Eventual Consistency

Why the price you see on Amazon might be different from the price your friend sees, for a second.

The two extremes

In a single database, every read sees the latest write. That is called strong consistency. It is simple, correct, and what you expect.

In a distributed system with replicas, caches, and data centers in different places, keeping every copy perfectly in sync is physically impossible at scale. The speed of light alone gives you milliseconds of lag.

You have two design choices.

Strong consistency sends all writes through one source of truth and forces readers to check it. Slow but always correct.

Eventual consistency lets copies drift apart for a short time. Writes spread in the background. Reads might see an older version for a brief window. Faster, but you have to design for the stale view.

What "eventual" feels like in real life

Some concrete examples.

You update your profile name on Twitter. Your own timeline updates right away. But your friend's feed shows your old name for about 10 seconds. That is eventual.

You buy the last copy of a book on Amazon. Another shopper still sees "in stock" for a few seconds before the inventory update spreads. That is eventual.

You like a tweet. Your screen says 42 likes. Another person looking at the same tweet sees 41 for a moment, then 42. That is eventual.

For most read-heavy apps, this is fine. Users put up with small delays. The speed and availability gains are huge.

But for some actions, this is not okay. Bank transfers. Ticket sales. Anything where two people might race for the last item. You need stronger promises.

The CAP theorem in one line

Distributed systems theorists sum this up with the CAP theorem.

When the network between your nodes is broken, you must choose between Consistency and Availability.

In plain words. When the network connection between your machines breaks (and it sometimes does), you have two options.

You can refuse to serve requests on the disconnected side. That is consistent. But some users cannot use the app.

You can keep serving from the disconnected side. That is available. But the data there is stale.

You do not get both during a partition. Most real systems pick "available and eventually consistent." They keep serving, accept some stale data, and reconcile once the partition heals. Databases that pick "consistent over available," like a single-leader SQL setup with strict transactions, refuse writes when they cannot reach the primary.

How to design around stale data

Eventual consistency is fine if you design for it.

Read your own writes. When a user does a write, send their next few reads to the primary instead of a replica. They see their own change right away. Other users still see the eventually consistent view.

Optimistic UI. When the user clicks Like, show the like in the UI immediately. Send the real write to the server in the background. If it fails, reconcile. The user feels an instant response.

Conflict resolution. If two replicas accept conflicting writes during a partition, you need a rule for how to merge them later. Common choices are last-write-wins (simple but can lose data), CRDTs (math structures that always merge cleanly), or app-level logic like merging the contents of two carts.

The whole field of distributed systems is, in a way, the study of dealing gracefully with eventual consistency.

Now build it yourself →