Direct answer
Eventual consistency means that after a write stops happening, all replicas of the data will eventually converge on the same value, but there is no guarantee about how long that takes or what a reader sees in the meantime. It trades a temporary window of staleness for lower write latency and higher availability, and it is the right default for data where a slightly-stale read is harmless, and the wrong default where a stale read causes real damage.
Structured elaboration
Whether eventual consistency is acceptable comes down to one question: what does the application actually do with a stale read?
- Tolerant workloads: anything the user does not act on financially or safety-critically in the moment. Order history, delivery-tracking analytics, recommendation feeds, and dashboard counters are all fine to serve slightly stale, because a few seconds of lag has no real consequence.
- Intolerant workloads: anything where a stale read causes an incorrect real-world action. Capturing a payment, decrementing the last unit of inventory, or checking an account balance before a withdrawal are all cases where a stale read can produce double-charges, oversells, or overdrafts.
The dividing line is not the technology, it is the cost of being wrong for a few hundred milliseconds to a few seconds.
Worked example
Picture a food-delivery app.
- Acceptable: the "your driver is 4 stops away" tracker and the "orders this month" analytics dashboard read from an asynchronously-replicated read replica. If that replica is a second behind, the customer sees the driver's position update a second late, which nobody notices.
- Not acceptable: the moment a customer taps "place order" and their card is charged. If two replicas of the payment-capture record briefly disagree about whether the charge already happened, a naive retry can charge the card twice. This path needs a strongly-consistent read (or an idempotency key tied to the order, so a retry is safe regardless of replication lag).
A second, different domain shows the same trade-off with a different shape of consequence. Picture a social-feed app instead: a user posts a photo and immediately likes their own post. Because "post visible to followers" and "like count" are two independently-replicated pieces of data, a reader can briefly see a user-visible anomaly: the poster's own like counted in the total but the post itself not yet visible in a follower's feed, or the reverse, the post visible but the like count still showing the pre-like value. Nobody's money or safety is at stake here, so full strong consistency for every post and every counter would be a wildly expensive fix for a cosmetic problem. The mitigation is much cheaper than moving to strong consistency everywhere: have the poster's own client apply an optimistic local update (show "liked", show the post as posted, immediately, from the write they just issued) regardless of what the shared aggregate view currently shows, while everyone else's feed is allowed to catch up asynchronously over the next second or two. This is the same "read-your-writes for the writer only" idea as the food-delivery payment case, just applied to a cosmetic anomaly instead of a financial one, which is the point: the fix pattern generalizes across very different domains and severities.
Trade-offs and mitigations
You rarely need to make the whole system strongly consistent to fix this. Options, cheapest first:
- Read-your-writes for the writer only: route the customer's own immediate post-order reads (or, in the social-feed case, the poster's own view of their own post) to the primary or a replica guaranteed to have applied their write, while everyone else's dashboard or feed keeps reading from a lagging replica.
- Idempotency keys on the write path itself, so even if a client retries under uncertainty, the payment is captured at most once regardless of what any read shows.
- Reserve strong consistency for the specific field that matters (payment status, inventory count for the last few units) rather than promoting the entire order record, or the entire social graph, to strong consistency, which would slow down the majority of reads that never needed it.
The common mistake is treating "eventual consistency" as a single global switch. In practice it is a per-field decision: most of an application, whether it is a checkout flow or a social feed, can tolerate staleness, and only the handful of fields tied to money, safety, or the acting user's own immediate perception of their own action need the latency cost of strong consistency.