Menu

Earn Premium with Referrals

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

See how it works and start inviting friends.

Request Coalescing
HLD

Request Coalescing

Many identical concurrent requests, one computation — collapsing duplicate work at every layer.

The Ubiquitous Waste

 200 users hit the uncached same key within the same instant:

 naive: 200 identical db queries + 200 cache SETs
 needed: ONE query; everyone shares the answer

 this waste appears at EVERY layer:
 - in-process: goroutines/threads duplicating fetches
 - cross-pod:   each pod independently missing the shared cache
 - cross-region: every region refilling from origin
 coalescing = the fix at whichever layer it hurts.

In-Process Coalescing (Singleflight)

 Go's singleflight pattern — the canonical form:

 calls for key K arrive concurrently:
   first caller starts the actual fetch
   others SUBSCRIBE to that flight's result channel
   result lands → all callers receive the SAME value

 var g singleflight.Group
 v, err, shared := g.Do(key, func() (any, error) {
     return db.Query(key)
 })

 semantics: per-key mutex on EXECUTION, broadcast on completion.
 zero coordination infrastructure — pure process-local.

Cross-Pod Coalescing

 pods can't share memory — coordinate through the cache store:

 distributed lock variant:
   SET fill:key pod-7 NX EX 3        ← one pod wins refill rights
   winner: fetch + set + DEL lock
   losers: poll cache briefly (50ms), then fall through to source
           (bounded — never wait forever on a dead winner)

 lease discipline matters:
 - lock TTL short (3-5s) so crashes can't wedge the key
 - losers' timeout bounded; worst case = old behavior (own fetch)

Where Each Level Applies

LayerToolProtects
Function callsingleflightDuplicate work in one pod
Cache refillfill locks / SWRDB from herd (stampede lesson)
Expensive computejob dedup tableFare engine, PDF renders
Upstream APIsrequest dedup windowVendor rate limits
 compute example: fare quote service
   quotes keyed by route+time-bucket;
   singleflight collapses 50 simultaneous quote requests
   into one pricing-engine call — vendor bill drops 98%.

The Subtle Costs

 - LATENCY COUPLING: all subscribers wait for the slowest flight
   (mitigation: leader does stale-if-error fallback on failure)
 - THUNDERING COMPLETION: result broadcast wakes N waiters at once
   (usually fine; huge N → stagger responses)
 - KEY CANONICALIZATION required or flights fragment:
   "?sort=price&color=red" vs "?color=red&sort=price" must agree

Combining With the Stampede Toolkit

 full hot-key defense stack:

 ttl jitter          prevents synchronized expiry (prevention)
 stale-while-revalidate   serves old while refreshing (absorption)
 SINGLEFLIGHT/FILL LOCKS  guarantees one db query (guarantee)
 L1 local caches          spreads residual load across pods (dilution)

 layers compose; each covers a failure mode of the previous.

Interview Framing

“1000 requests arrive for one cold key” expects: name the pattern (coalescing/singleflight), show both scopes (in-process AND distributed fill-lock with lease TTLs), note canonicalization as the practical gotcha. One sentence connecting it to stampede defenses shows you see the system, not the trick.

My Private Notes

Notes are auto-saved locally to this device.