Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Probabilistic Early Refresh
HLD

Probabilistic Early Refresh

XFetch — dissolving expiry herds with probability instead of locks, by refreshing before TTL dies.

The Insight

 stampedes happen AT expiry because everyone waits for death,
 then races. XFetch (probabilistic early recomputation) asks:
 why expire at all? refresh EARLY, by lottery:

 on each read of value with age a and ttl T:

   fetch_probability = exp( -k × Δ × (a/T)² )

   where Δ = expected refetch time as fraction of T

 behavior:
   age ≈ 0        → probability ~0     never refresh early
   age → T        → probability climbs smoothly toward 1
   one request "wins" the lottery slightly before expiry
   → value refreshed BEFORE the herd moment exists

Why the Math Works

 the quadratic term shapes everything:

 early in life:  (a/T)² tiny  → almost nobody refreshes
 near expiry:    curve steepens → SOMEONE refreshes soon
 first refresher resets age → race vanishes

 across many reads per key, expected number of "early birds"
 converges to ~1-2 — the herd becomes a trickle WITHOUT:
 - distributed locks
 - waiting/queueing
 - stale-serving tradeoff (value stays fresh!)

Implementation Sketch

 store alongside value: fetched_at timestamp

 def get(key):
     entry = cache.get(key)
     if entry is None: return refill(key)          # true miss
     age = now() - entry.fetched_at
     if random() < exp(-K * DELTA * (age/TTL)**2):
         async_refill(key)                          # non-blocking!
         return entry.value                         # still fresh
     return entry.value

 K tunes eagerness (typical 1-10);
 DELTA ≈ refetch_time / ttl (often ~0.01)
 async_refill itself wrapped in singleflight for belt+suspenders.

vs The Alternatives

DefenseCoordinationServes stale?Blocks callers?
Fill mutex/locksDistributed locknowaiters wait
Stale-while-revalidatenoneyes (briefly)no
TTL jitternonenoonly at true expiry
XFetchNONEnono
 XFetch's unique selling points: zero infrastructure
 (pure client logic) and it PREVENTS rather than absorbs.
 costs: slight extra background load (~1-2x refresh rate),
 randomness in metrics (refresh timing varies).

Where It Shines

 ✓ very-hot keys where even ONE db hit at expiry is expensive
   (homepage payload, config, feature flags)
 ✓ systems avoiding distributed-lock complexity/correctness risk
 ✓ combined with jitter + singleflight as the no-locks trifecta

 less critical for long-tail keys (misses are cheap there —
 the herd needs a crowd, rare keys don't draw one).

Interview Framing

Most candidates know fill-locks; mentioning probabilistic early refresh BY NAME and its property set — “no locks, no staleness, prevents instead of absorbs” — is a genuine differentiator in caching discussions. Sketch the formula shape verbally (probability rises quadratically toward expiry), state the async-refresh detail, and place it in the toolkit stack.

My Private Notes

Notes are auto-saved locally to this device.