Software Architecture / Editorial solution guide
Diagnose tail latency when cache misses amplify source work
Separate cache key errors, expiry stampedes, retry amplification, and source saturation using a controlled evidence plan.
Read-only knowledge base ยท No public comments
Recognize the symptoms
A fictional catalog is usually responsive but becomes slow when a popular entry expires. Average latency remains acceptable while a minority of requests wait much longer. Adding application replicas increases database work and does not reliably improve the slow period. No live measurements are supplied by this guide.
Understand the likely causes
- Possible explanations include many concurrent refreshes for one key, inconsistent keys that prevent reuse, unbounded fallback after a cache fault, and retries at several layers. A slow source can also cause the cache symptom rather than result from it. Test the timing and relationship of observations before assigning causality.
Define the slow operation and its measurement window
Choose one catalog query shape, response boundary, synthetic dataset, and observation window. Compare end-to-end latency distribution with cache misses, source calls, pending requests, and errors. Separate a client retry from a distinct user operation so the denominator stays meaningful. Inspect whether missing telemetry coincides with the incident; an incomplete histogram can make tail behavior look better than it is. Do not compare a warm-cache quiet interval with a cold-cache busy interval and attribute the whole difference to a code change.
Inspect key construction without exposing private data
List result-changing dimensions such as language, representation version, authorized visibility, and normalized query parameters. Check whether equivalent requests unexpectedly create distinct keys or distinct permitted results collide. Use synthetic fixtures and safe key summaries. A growing key count is evidence to investigate, not proof of a defect: legitimate languages or pages may account for it. Avoid logging raw user searches or identifiers merely to understand reuse. Review the contract that tells you which requests should actually share a cached value.
Fixture A: workshop ws-4, language en, representation v2
Fixture B: workshop ws-4, language ar, representation v2
Expected: different keys
Fixture C: same as A after harmless parameter normalization
Expected: same key as A, only if contract says the result is equivalent
The expected relationship follows the declared query contract. No cache keys or user searches are collected from a running service.
Look for clustered misses and concurrent refreshes
A stampede hypothesis predicts a burst of source requests for the same expired representation, overlapping refresh duration, and growing source wait. Compare it with a key-fragmentation hypothesis, which predicts low reuse across many logically equivalent keys. A cache outage predicts broader fallback behavior. These patterns can coexist, so use a narrow isolated experiment that changes one factor. Request coalescing and bounded refresh concurrency may help, but their cancellation, failure, and stale-serving behavior also need verification.
Protect the source while preserving freshness semantics
Choose a correction that fits the evidence: normalize keys, coalesce refresh work, bound fallback concurrency, or reduce duplicate retry ownership. Define whether stale descriptions may be returned and how freshness is communicated. Never use an old cached seat count to approve a reservation. A safe correction can intentionally reject some reads rather than overload the authoritative store, but the response must be explicit. The sample acceptance criteria are a proposed lab plan and contain no universal timeout, pool size, or expiry recommendation.
experiment: isolated concurrent misses for one synthetic public description
required: bounded source refresh work
required_outcome: correct language and declared freshness policy
failure_case: cache unavailable
stop: unexpected source saturation or correctness mismatch
This document does not generate concurrent traffic. A real experiment must use an authorized isolated source and record actual observations separately.
Verify the fix
Compare the same isolated workload before and after correction, including cold miss, warm hit, simultaneous expiry, and cache unavailability. Verify tail latency, errors, source-call count, and returned content together. Report environment limits and do not generalize a fixture result to production capacity.
Keep it from recurring
- Keep cache freshness contracts and bounded fallback behavior explicit, review retry ownership across layers, and test expiry behavior when query shapes or source capacity change. Monitor old work and source saturation alongside hit ratio so a favorable aggregate does not hide an overloaded miss path.