⏱ 6 min read
Not a bug. A trade-off you need to understand.
Update your profile picture, refresh the page on your phone, and for a second the old one is still there. Is that a bug? Most people's instinct is yes - I just saved this, why doesn't everything show it immediately?
It isn't a bug. It's eventual consistency, and if you build distributed systems, you're relying on it constantly - whether you've designed for it or not.
The promise everyone wants is simple: you update something, and every service, every region, every cache sees it instantly. One version of the truth, always. That's strong consistency, and it's a completely reasonable thing to want.
It's also expensive. Guaranteeing that every node agrees before a write is considered done means coordination - and coordination across a network, especially across regions, means waiting on round trips you don't control. Do that on every write, at scale, and your system's latency is now bounded by your slowest node and your worst network hop.
So most distributed systems don't do that. They accept a weaker guarantee in exchange for speed and availability, and call it eventual consistency.
Here's the mechanism: a write lands on one node (or a small subset of nodes). The other nodes find out later, through replication, gossip, or some other propagation mechanism - not as part of the original write. If no new updates come in, every node eventually converges on the same value.
That word "eventually" is doing a lot of work, and it's worth being precise about it. It's not a promise about timing - it's a promise about outcome. Given enough time and no further writes, all replicas agree. In practice, "eventually" is usually milliseconds, sometimes seconds, and only occasionally something you'd actually notice. But the guarantee itself says nothing about how fast - it only says eventually, which is a liveness guarantee, not a timing one.
This is where the CAP theorem shows up, and it's less abstract than it sounds once you connect it to a decision you're actually making. CAP says a distributed system, when it hits a network partition, has to choose: stay consistent (every node sees the same data) or stay available (every request gets a response, even if it's not the very latest data). You can't fully have both during that partition.
Eventual consistency is the deliberate choice of availability over strong consistency. You're saying: I'd rather my system keep responding, even with slightly stale data on some node somewhere, than have it refuse to answer while it waits to be sure everyone agrees. For a lot of systems, that's exactly the right call - and it's worth naming it as a call, not something that just happens to you.
This isn't exotic. If eventual consistency sounds like something only distributed-systems specialists deal with, consider how much of your daily infrastructure already works this way.
DNS is the oldest example - update a record and it can take minutes to propagate everywhere, not milliseconds. CDNs cache content at edge nodes and take time to invalidate it after a change. Social media feeds - likes, comments, view counts - propagate asynchronously; nobody expects a like count to update everywhere in the same instant. And if you run a primary/replica database setup, your read replicas are, by construction, eventually consistent with the primary. There's always some lag, even if it's usually small enough that nobody notices.
You've been relying on eventual consistency for years. The only question is whether you've been designing for it on purpose.
Designing for eventual consistency on purpose looks different from tolerating it by accident. A few things that actually help:
And know the specific failure patterns to watch for, because they're the same handful every time: reading your own write and getting the stale value back (you just saved this - why doesn't it show?); stale aggregates, where a count or total lags behind the records it's summarizing; two users updating the same record concurrently, with one silently overwriting the other; and downstream actions - an email, a notification - firing off the back of data that's already out of date by the time they run.
None of these are exotic bugs. They're the predictable consequences of eventual consistency meeting code that was written as if it were strongly consistent.
Not every part of your system should take the eventually-consistent trade, either. Financial transactions - debits and credits - need to be atomic. Inventory reservation needs strong consistency, or two customers can both "successfully" claim the last item in stock. A revoked authentication token needs to be invalid immediately, not eventually. Eventual consistency is a sensible default for a lot of your system. It isn't a universal rule, and treating it as one is exactly how you end up debugging a double-sold item at 2am.
Eventual consistency trades "always correct" for "always available" - and for most of what you build, that's the right trade. The mistake isn't choosing it. The mistake is not knowing you've chosen it.
The worst eventual consistency bugs I've seen weren't caused by the trade-off itself. They were caused by nobody realizing the trade-off had been made, until a user noticed their own change had disappeared.
PS: Let me know if I missed anything - ping me on Twitter/X or LinkedIn, and follow along there if you'd like more of this. Let's chat.
eventual-consistency cap-theorem distributed-systems data-consistency