Replica Lag Routing
also called Read Routing, Primary Pinning
Deciding, per read, whether it may be served by an asynchronous replica - the operational discipline that makes read scaling safe.
Read replicas are one of the highest-leverage moves in data architecture: they scale reads nearly linearly, are operationally well understood, and are reversible. The first thing they break is [[read-your-writes]], and how a team responds to that decides whether replicas are an asset or a liability.
The two common responses are both wrong. Abandoning replicas throws away the scaling win. Ignoring the problem ships a product where saving something and immediately seeing the old value is routine.
The right response is routing: classify reads, send the small set that genuinely requires freshness to the primary, and let everything else use replicas.
Why it matters
Users have no intuition about whether another person's edit is visible yet, and complete intuition about whether their own is. A violated read-your-writes guarantee does not look like eventual consistency to a user — it looks like the system lost their work, and they respond by editing again, which creates a second problem.
Getting this one classification right is what lets everything else in the system be eventually consistent.
Implementation patterns
- Sticky primary reads after a write. For a short window after a user writes, route that user's reads to the primary. Simple, effective, and affordable because the extra primary load scales with write rate rather than read rate.
- Replication position tokens. The write returns a log position; subsequent reads require a replica at or past it, or fall through to the primary. Precise, gives the guarantee only where needed, and costs plumbing through the client and router.
- Render from the write response. The mutation returns the new state and the UI renders that rather than re-reading. Free, and only covers the immediate interaction.
- Monotonic reads as a companion. Pin a session to one replica so a user never sees time go backwards by bouncing between replicas at different positions — which is arguably more confusing than staleness.
Industry example
A marketplace seller edits a listing and is shown the previous version, because the read landed on a replica microseconds behind. The seller edits again. Now there are two edits in flight and the seller is convinced the platform is broken.
The pragmatic resolution used across marketplaces, social platforms and content systems is the same: identify the small set of reads that must be fresh — a user reading their own recent write — and route only those to the primary. A buyer seeing a listing edit a second late is invisible. A seller seeing their own edit vanish is a support ticket.
The other half is operational and often neglected: a lagging replica must be removed from the read pool. A replica that is minutes behind but healthy passes every liveness check and serves confidently wrong data to everyone, which is worse than having one fewer replica.
Failure scenarios
- Sticky routing keyed to a connection rather than a user, so a load-balanced client loses stickiness on a new connection.
- Cross-device sessions. A user writes on mobile and reads on desktop; session stickiness does not span devices, so the guarantee silently does not apply.
- A cache in front of the replica, which reintroduces staleness even when replica routing is correct.
- Alerting on replica health but not on lag. The characteristic failure is a connected, apparently healthy replica falling minutes behind.
- Applying the guarantee everywhere, which sends all reads to the primary and abandons the reason replicas were introduced.
Trade-offs
Providing it costs primary load, routing complexity and a session concept that must be threaded through the stack. Not providing it costs user trust in a way that is hard to attribute — users do not report "replication lag", they report that the product is unreliable.
The useful discipline is to name, explicitly, which reads require it. In most systems the honest list is short: a user's own recently modified content, and any read that feeds a subsequent write decision.
Interview question
"You add read replicas and immediately get reports that saved changes 'do not stick'. Walk me through three ways to fix it, the cost of each, and which reads you would leave eventually consistent."