A user updates their profile and is redirected to the profile page, which shows the old values. They update again. Same result. They conclude the feature is broken and contact support.
Nothing is broken. The write went to the primary, the read went to a replica, and the replica had not yet applied the change.
What changed in 2026
- Per-query routing became standard. Choosing primary or replica per query, rather than globally, became the expected pattern.
- Time-based lag monitoring displaced byte-based. Measuring how far behind in seconds became the norm.
- Framework support improved. More ORMs gained first-class read/write splitting with routing hints.
- Session-consistency mechanisms spread. Tracking a write position and routing subsequent reads accordingly became available in more systems.
Where lag comes from
The primary commits a change and streams it to replicas, which apply it. Several things can delay that.
Replay is largely single-threaded in many systems, while writes on the primary are concurrent. A burst of parallel writes can be produced faster than one replay process applies them.
Network transfer takes time, particularly across regions.
Conflicting queries on the replica can pause replay. A long-running read on the replica may conflict with a change that would invalidate what it is reading, and depending on configuration the replica either delays replay or cancels the query.
Large transactions replay as a unit. A bulk operation on the primary appears on the replica only when its whole transaction is applied.
That third cause is the one that surprises people: a long analytical query on the replica can cause the lag it then suffers from.
Measure in time
Byte-based lag — how many bytes behind the replica is — is nearly useless operationally. A hundred megabytes behind means nothing without knowing the write rate.
Time-based lag answers the question that matters: how stale is data on this replica right now. Most systems expose it directly.
| Lag |
Typical acceptability |
| Milliseconds |
Fine for nearly everything |
| A second or two |
Fine for most reads |
| Tens of seconds |
Analytics only |
| Minutes |
Investigate |
| Growing steadily |
Replica cannot keep up |
The distinction between a lag that is high and stable versus one that is growing matters most. Stable lag means the replica keeps up with a delay. Growing lag means it cannot, and it will keep falling behind until something changes.
Route by requirement
The workable pattern is deciding per query rather than globally.
To the primary: anything read immediately after a related write, anything used to make a decision with consequences, and anything where a user would notice staleness.
To a replica: analytics, reporting, list views, search, and anything where a second of staleness is invisible.
Read-your-own-writes is the specific case that needs handling. Three approaches: route reads to the primary for a short window after a write from that session; track the write position and route to a replica only once it has caught up past that position; or route all reads within a request to the primary if the request performed a write.
The second is the most precise and requires system support. The first is crude and works everywhere.
Common mistakes
- Routing all reads to replicas. Guarantees read-after-write failures.
- Byte-based lag monitoring. Says nothing about staleness.
- Alerting on a lag threshold only. Growth matters more than level.
- Long analytical queries on a replica serving user traffic. Causes the lag it suffers from.
- No handling for read-your-own-writes. The case users notice.
- Assuming failover is instant. A promoted replica may be missing recent writes.
- Not testing with realistic lag. Local development has none.
FAQ
How much lag is acceptable?
Depends entirely on the query. Sub-second is fine for nearly everything; analytics tolerates far more. The useful question is per query, not per system.
Can I eliminate lag?
Synchronous replication removes it at the cost of write latency, since the primary waits for the replica — see synchronous replication. Most systems accept some lag rather than pay that on every write.
What happens on failover?
An asynchronously-replicated replica promoted after a primary failure may be missing the most recent writes. That data loss window is the cost of asynchronous replication and should be an explicit decision.
Does logical replication lag differently?
It has its own characteristics and constraints — see logical replication.
Where to go next
For the zero-lag alternative and its cost, read synchronous replication. For the flexible replication type, logical replication, and for the underlying mechanism, read replicas explained.