Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 4

Eventual Consistency: Variants Compared

Recommended resources

In our last lesson, we established that the PACELC theorem provides a more complete model than CAP by accounting for the trade-off between latency and consistency during normal system operation. This led us to a crucial insight: many high-performance, highly available systems deliberately choose lower latency at the cost of strong consistency. This lesson delves into what that choice means in practice.

When a system forgoes strong consistency, it doesn't necessarily descend into chaos. Instead of a single, rigid guarantee, engineers have developed a spectrum of weaker, more nuanced consistency models. Today, we will compare three of the most important variants of eventual consistency: read-your-writes, monotonic reads, and bounded staleness. Understanding these models is critical for designing and reasoning about applications built on modern distributed databases, where making the right trade-off directly impacts user experience and system performance.

From "Pure" Eventual to Predictable Guarantees

At its most basic, eventual consistency simply promises that if no new updates are made to a data item, all replicas will eventually converge to the same final value. The classic example is DNS, where changes can take hours to propagate. However, for interactive applications, this is often too weak. The period of divergence, known as the "inconsistency window," is unbounded and offers no predictability to the application developer or the end-user.

To address this, systems provide stronger, more specific guarantees that hold true even while the system as a whole is still converging. These are often client-centric, meaning they define the behavior a single user's session can expect. Let's explore the most common ones.

The following article by Amazon's CTO, Werner Vogels, is a canonical resource on this topic. It provides clear, practical definitions for these consistency models.

Eventually Consistent

This article frames the discussion around client-side consistency and defines several key variants of the eventual consistency model.

First, read the introductory sections on client-side consistency to set the stage. Next, read the definitions of Strong and Weak consistency as a baseline. Finally, focus on the core section that defines the key models for this lesson: Causal consistency, Read-your-writes, and Monotonic read consistency. We will discuss Bounded Staleness separately.


Read-Your-Writes Consistency

As defined in the article, Read-Your-Writes (RYW) consistency is a straightforward and highly intuitive guarantee. It ensures that once a client has successfully written an update, any subsequent reads it performs will return that updated value (or a newer one).

Imagine you update your profile picture on a social media app. Without RYW, you might hit save, refresh the page, and see your old picture again because your read request was routed to a replica that hadn't yet received your update. This is a jarring user experience. RYW prevents this specific anomaly.

The video below provides a great example using a shopping cart.

Consistency | Azure Cosmos DB Essentials Season 1

This video from Microsoft Azure explains several consistency models in the context of Cosmos DB. The section on Session Consistency is directly applicable, as it is built upon the Read-Your-Writes guarantee.

Watch the segment from session consistency. The speaker uses the examples of an online shopping cart and a wall post to illustrate why a user must be able to see their own writes immediately.

How is RYW typically implemented? As the "All Things Distributed" article notes, a common strategy is to make client sessions "sticky." The system's load balancer ensures that all requests from a particular client session are routed to the same replica. Since that replica processed the write, it can immediately serve the correct data for subsequent reads from the same client.


Monotonic Reads Consistency

Monotonic Reads provides a different kind of guarantee. It ensures that if a client reads a value, any subsequent reads by that same client will never return an older value. The sequence of data a client sees only ever moves forward in time.

Consider an application that displays the status of a long-running background job: "Processing" -> "Generating Report" -> "Complete". If a user refreshes the page, they should not see the status revert from "Complete" back to "Processing". This is precisely what Monotonic Reads prevents. This anomaly can happen if the user's first read hits an up-to-date replica, but their second read hits a different, lagging replica.

Like RYW, Monotonic Reads can also be implemented using sticky sessions, ensuring the client consistently reads from a replica whose state is only moving forward from that client's perspective.


Bounded Staleness Consistency

While RYW and Monotonic Reads are about the order of operations a client sees, Bounded Staleness is about the freshness of the data. It provides a quantitative guarantee that the data a client reads will not be stale beyond a specific bound. This bound can be defined in two ways:

  1. Time: Reads will lag the latest write by at most seconds.
  2. Versions: Reads will be at most versions behind the latest write.

This model is a powerful compromise, offering much lower read latency than strong consistency while providing a much stronger guarantee than pure eventual consistency. You encountered this concept in the last lesson when we discussed Google Spanner, which famously offers bounded staleness reads.

The diagram below illustrates the concept. A primary node takes writes and asynchronously syncs them to replicas. A client reading from a replica is guaranteed to get data that is within the defined staleness bound (N ops/time).

This diagram shows a write operation going to a primary database node. Replicas are synchronized from this primary within a bound of 'N ops/time'. A separate user can read data from these replicas, with the assurance that the data is not older than the specified bound.

The following video segment explains Bounded Staleness with a practical example.

Consistency | Azure Cosmos DB Essentials Season 1

Let's return to the Azure video, which provides a concise explanation of Bounded Staleness.

Watch the segment from bounded staleness. It explains how you can define a staleness window by time or number of updates and uses a mobile delivery app as a tangible use case.

A key takeaway here is the operational consequence mentioned in the video: to enforce the bound, the system might need to throttle writes if replicas are falling too far behind. This is a direct manifestation of the PACELC trade-off—sacrificing some performance (write latency/throughput) to maintain a specific level of consistency.


Comparing the Models

These three models address different potential anomalies of eventually consistent systems. They are not mutually exclusive; a sophisticated database can offer combinations of these guarantees. The table below gives a high-level, qualitative comparison of various guarantees, including the ones we've discussed.

This table compares various consistency models on the dimensions of Consistency, Performance, and Availability. Eventual Consistency is rated as 'poor' for consistency but 'excellent' for performance and availability. Monotonic Reads and Read My Writes are rated as 'okay' or 'good' across the board, representing a middle ground. Bounded Staleness is rated 'good' for consistency but 'poor' for availability.

When analyzing this table, it's important to interpret the ratings with nuance. For instance, "Bounded Staleness" is rated as having "poor" availability. Why might that be? Because if a client requests a read with a 1-second staleness bound, and no nearby replica can satisfy that bound, the read must either fail or be rerouted to a primary/more up-to-date replica, incurring high latency. In contrast, a simple "Eventual" read could be satisfied by any replica, regardless of how stale it is, thus maximizing availability.

This highlights a core principle for a Principal Engineer: there is no universally "best" model. The right choice is a function of the application's specific requirements.

  • Does a user need to see their own updates immediately? You need Read-Your-Writes.
  • Does a user need to see a timeline of events that never goes backward? You need Monotonic Reads.
  • Is it acceptable for data to be slightly stale, but not too stale? Bounded Staleness is an excellent fit.

Conclusion

Today we moved beyond the simple dichotomy of strong vs. eventual consistency and explored the practical, intermediate guarantees that make eventually consistent systems usable for a wide range of applications.

Here are your key takeaways:

  • Eventual consistency variants provide stronger, predictable behaviors compared to the "pure" model, primarily by defining what a single client session can expect.
  • Read-Your-Writes (RYW) ensures a client sees its own updates, a fundamental requirement for most interactive applications.
  • Monotonic Reads ensures a client's view of data only moves forward in time, preventing confusing backward jumps in state.
  • Bounded Staleness provides a quantitative limit on data freshness, offering a powerful compromise between strong consistency and low-latency reads. This is a key feature in modern distributed databases like Spanner.
  • These models are often implemented via client session stickiness, routing a client's requests to a consistent replica to maintain these guarantees.

You now have a more granular understanding of the "EL" (Else/Latency) side of the PACELC theorem. You can analyze not just whether a system prioritizes latency, but what specific consistency guarantees it provides in exchange.

In our next lesson, we will tie these concepts together by formally exploring session guarantees. We'll see how guarantees like RYW and Monotonic Reads are bundled into a "session" to provide a powerful and pragmatic programming model for building robust client applications on top of distributed databases.