Follower read types
A strong follower read is a read taken from a table. Such tables are optimized for low-latency reads from every region in the database. The tradeoff is that writes will incur higher latencies from any given region, since writes have to be replicated across every region to make the global low-latency reads possible. For more information about global tables, including troubleshooting information, see . A stale follower read is a historical read taken from the nearest replica. You should use stale follower reads only when your application can tolerate reading stale data, since the results of stale follower reads may not reflect the latest writes against the tables you are querying. The following table summarizes the read types and how to accomplish them. | Strong Reads | Stale Reads -----|-----------|---------------------------------------------------------------- Only From Leaseholder |SELECT | N/A
From Nearest Replica | SELECT on a GLOBAL table or a long-running SELECT whose read timestamp has fallen behind the | SELECT with AS OF SYSTEM TIME <historical-timestamp-function>
Stale follower reads
CockroachDB provides the following types of stale follower reads:- Exact staleness read: A historical read as of a static, user-provided timestamp. See Exact staleness reads.
- Bounded staleness read: A historical read that uses a dynamic, system-determined timestamp to minimize staleness while being more tolerant to replication lag than an exact staleness read. See Bounded staleness reads.
Stale follower reads are always served from a consistent view; CockroachDB does not allow a historical read to view uncommitted data.
Exact staleness reads
An exact staleness read is a historical read as of a static, user-provided timestamp. For requirements and limitations, see Exact staleness reads and long-running writes and Exact staleness read timestamps must be far enough in the past.When to use exact staleness reads
Use exact staleness follower reads when you:- Need multi-statement reads inside .
- Can tolerate reading older data (at least 4.2 seconds in the past), to reduce the chance that the historical query timestamp is not quite old enough to prevent blocking on a conflicting write and thus being able to be served by a local replica.
- Do not need the increase in availability provided by bounded staleness reads in the face of or other failures.
- Need a read that is slightly cheaper to perform than a bounded staleness read, because exact staleness reads don’t need to dynamically compute the query timestamp.
Run queries that use exact staleness follower reads
Any with an appropriate value is an exact staleness follower read. You can use the conveniencefollower_read_timestamp(), which returns a that provides a high probability of being served locally while not blocking on conflicting writes.
Use this function in an AS OF SYSTEM TIME statement as follows:
Exact staleness follower reads in read-only transactions
You can set the clause’s value for all operations in a read-only :Bounded staleness reads
A bounded staleness read is a historical read that uses a dynamic, system-determined timestamp to minimize staleness while being more tolerant to replication lag than an exact staleness read. Bounded staleness reads also help increase system availability, since they provide the ability to serve reads from local replicas even in the presence of network partitions or other failures that prevent the SQL gateway from communicating with the leaseholder.When to use bounded staleness reads
Use bounded staleness follower reads when you:- Need minimally stale reads from the nearest replica without blocking on . This is possible because the historical timestamp is chosen dynamically and the least stale timestamp that can be served locally without blocking is used.
- Can confine the read to a single statement that meets the bounded staleness limitations.
- Need higher availability than is provided by exact staleness reads. Specifically, what we mean by availability in this context is:
- The ability to serve a read with low latency from a local replica rather than a leaseholder.
- The ability to serve reads from local replicas even in the presence of a network partition or other failure event that prevents the SQL gateway from communicating with the leaseholder. Once a replica begins serving follower reads at a timestamp, it will always continue to serve follower reads at that timestamp. Even if the replica becomes completely partitioned away from the rest of its range, it will continue to stay available for (increasingly) stale reads.
Run queries that use bounded staleness follower reads
To get a bounded staleness read, use one of the following built-in functions:| Name | Description |
|---|---|
with_min_timestamp(TIMESTAMPTZ, [nearest_only]) | Defines a minimum at which to perform the . The actual timestamp of the read may be equal to or later than the provided timestamp, but cannot be before the provided timestamp. This is useful to request a read from nearby followers, if possible, while enforcing causality between an operation at some point in time and any dependent reads. This function accepts an optional nearest_only argument that will error if the reads cannot be serviced from a nearby replica. |
with_max_staleness(INTERVAL, [nearest_only]) | Defines a maximum staleness interval with which to perform the . The timestamp of the read can be at most this stale with respect to the current time. This is useful to request a read from nearby followers, if possible, while placing some limit on how stale results can be. Note that with_max_staleness(INTERVAL) is equivalent to with_min_timestamp(now() - INTERVAL). This function accepts an optional nearest_only argument that will error if the reads cannot be serviced from a nearby replica. |
-
Start the demo cluster with 3 nodes:
-
Issue a single-statement point query to a single row from a table at a historical by passing the output of the
with_max_staleness()to the clause:The query returns successfully. If it had failed with the following error message, you would need to troubleshoot your query to ensure it meets the conditions required for bounded staleness reads.You can verify using that the reason this query was able to perform a bounded staleness read is that it performed a point lookup from a single row:
Verify that CockroachDB is performing follower reads
To verify that a cluster is performing follower reads, go to the and add the metricfollower_reads.success_count to the time-series graph. The number of follower reads performed by your cluster will be shown.
To verify that a specific query uses a follower read, use to see the statement plan. For example, to test the preceding example:
-
Use the
\demo lsto list the connection parameters for all nodes:The output will list the connection parameters for each node: -
Open a new terminal and open the SQL shell on a non-leaseholder node. For example:
Identify the leaseholder node:
Connect to a node other than node 1 (such as node 3, using the preceding output):
-
Issue the statement on the non-leaseholder node:
In the preceding output,
used follower readindicates that the read was served by the follower replica.historical: AS OF SYSTEM TIME ... (bounded staleness)shows that it was a historical, bounded staleness read.
How stale follower reads work
Each CockroachDB range tracks a property called its , which means that no new writes can ever be introduced at or below that timestamp. The closed timestamp is advanced continuously on the leaseholder, and lags the current time by some target interval. As the closed timestamp is advanced, notifications are sent to each follower. If a range receives a write at a timestamp less than or equal to its closed timestamp, the write is forced to change its timestamp, which might result in a . With follower reads, any replica in a range can serve a read for a key as long as the time at which the operation is performed (i.e., the value) is less than or equal to the range’s closed timestamp. When a gateway node in a cluster receives a request to read a key with a sufficiently old value, it forwards the request to the closest node that contains a replica of the data — whether it be a follower or the leaseholder. For further details, see An Epic Read on Follower Reads.Known limitations
Exact staleness reads and long-running writes
Long-running write transactions will create with a timestamp near when the transaction began. When an exact staleness follower read encounters a write intent, it will often end up in a , waiting for the operation to complete; however, this runs counter to the benefit exact staleness reads provide. To counteract this, you can issue all follower reads in explicit :Exact staleness read timestamps must be far enough in the past
If an exact staleness read is not using an value far enough in the past, CockroachDB cannot perform a follower read. Instead, the read must access the . This adds network latency if the leaseholder is not the closest replica to the gateway node. Most users will to get a timestamp far enough in the past that there is a high probability of getting a follower read.Bounded staleness read limitations
Bounded staleness reads have the following limitations:- They must be used in a .
- They must read from a single row.
- They must not require an . In other words, the index used by the read query must be either a , or some other index that covers the entire query by all columns.
promo_codes table, which is why it cannot be used for a bounded staleness read.
For an example showing how to successfully perform a bounded staleness read, see .

