Knowledge Guide
HomeSystem DesignSystem Design Problems

hard Tracing a Request Against a Latency Budget (SLA)

An SLA is a budget you spend hop-by-hop, not a hope you check afterward

A latency SLA like "p99 < 200ms" is not one number to hit at the end — it is a budget you allocate across every hop a request touches before you build the path. Add each hop's cost as the request crosses it (load balancer, gateway, application logic, cache or database, serialization) and you get a running total against the budget. The moment that running total, plus a safety margin, would exceed the SLA, you know — at design time — which hop has to change: cached, parallelized, or bounded by a timeout. Tracing the budget turns "will this be fast enough?" from a guess into arithmetic.

A 200ms p99 budget waterfall: LB 5ms, gateway 3ms, app 10ms, cache hit 2ms or DB miss 20ms, serialize 5ms, leaving 175ms or 157ms slack; below, a tail-compounding inset shows 3 parallel calls each with 1% odds of a 40ms tail giving a 3% chance the hop itself is slow
A 200ms p99 budget waterfall: LB 5ms, gateway 3ms, app 10ms, cache hit 2ms or DB miss 20ms, serialize 5ms, leaving 175ms or 157ms slack; below, a tail-compounding inset shows 3 parallel calls each with 1% odds of a 40ms tail giving a 3% chance the hop itself is slow

Traced: a 200ms p99 budget for one API read

HopTypical costRunning totalRemaining budget
Load balancer + TLS termination5ms5ms195ms
Gateway (auth check)3ms8ms192ms
App logic10ms18ms182ms
Cache hit2ms20ms180ms
Serialize + egress5ms25ms175ms slack

On a cache hit, the request spends 25ms of its 200ms budget — 175ms of slack. Swap the cache hit for a cache miss that falls through to the database (20ms instead of 2ms) and the total becomes 5+3+10+20+5 = 43ms, leaving 157ms of slack. Both are comfortably inside the SLA on paper — but the miss path consumes 72% more of the budget than the hit path, which is exactly why cache hit ratio is a first-class capacity number, not an afterthought: it decides how often a request runs "cheap" versus how often it runs "expensive but still legal."

The slack is not free money — tail latency eats it

25ms or 43ms is the typical (mean-ish) path. The SLA is stated at p99, and typical-case sums badly underestimate p99 the moment any hop fans out internally. Say the "app logic" hop actually issues 3 independent calls in parallel — a user-info service, a recommendation service, an ads service — each with a typical latency of 8ms but its own p99 tail of 40ms (a 1% chance of hitting it, from GC pauses, a hot shard, lock contention). Using the fan-out math from tail-latency analysis:

P(≥1 of 3 hits its tail) = 1 − 0.99³ ≈ 3%

So the "app logic" hop's own p99 is worse than any single dependency's p99, purely from fanning out to three of them. Chain a few such hops together (gateway → app → cache/DB → downstream fan-out) and the request's real p99 compounds well past the sum of typical costs — it can approach or blow through the 200ms budget even though every individual hop "looks fine on average." Summing means tells you the best case; the SLA is a promise about the worst 1%.

How the budget forces decisions

Pitfalls

Judgment layer: how to actually allocate the budget

Budget-per-hop (top-down, before or while building) means allocating an SLA slice to each hop up front and designing to fit it — you gain early warning that an architecture is structurally incapable of meeting the SLA (e.g. discovering that 5 sequential service calls can never fit) before it's built. The cost is that the numbers are estimates until real traffic exists, so the allocation itself needs revisiting once measured.

Measure-and-optimize-hotspot (bottom-up) means shipping first, then profiling with real percentile data (the USE method, flame graphs) and fixing whichever hop is actually the biggest contributor to p99. You gain ground truth — you optimize what's really slow, not what you guessed would be slow — but you risk discovering the SLA is unmeetable only after the system is built, when the fix (e.g., turning a sequential chain into a parallel fan-out) is a structural change, not a tuning pass.

In practice: budget top-down during design to catch architectural dead ends early, then replace every estimated number with a measured percentile once the system is live, and re-run the same hop-by-hop trace against real p99s rather than typical-case guesses.

For parallel vs sequential calls specifically: parallelize whenever calls are independent (no data dependency) — you pay max() instead of sum(), at the cost of harder error handling (a partial failure now needs a per-call fallback) and a burst of simultaneous load on several downstreams at once instead of a trickle. Keep calls sequential only when one truly depends on the previous one's result.

For timeout allocation: a hop's timeout must fit the budget remaining at that point in the chain, not the SLA as a whole — the alternative (no timeout, or a timeout sized to the full SLA on every hop) trades a small amount of implementation complexity (fallback logic, timeout testing) for an unbounded worst case where a single slow dependency can consume the entire request.

Takeaways


Re-authored for this guide; budget-waterfall and tail-compounding diagram hand-authored as SVG. Synthesizes the Google SRE Book's error-budget framing and Dean & Barroso, "The Tail at Scale" (CACM 2013). See also: "Tail Latency & Fan-out Amplification," "Performance Engineering — USE Method & Flame Graphs," and the SLI/SLO/SLA error-budget page.

🤖 Don't fully get this? Learn it with Claude

Stuck on Tracing a Request Against a Latency Budget (SLA)? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Tracing a Request Against a Latency Budget (SLA)** (System Design) and want to truly understand it. Explain Tracing a Request Against a Latency Budget (SLA) from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Tracing a Request Against a Latency Budget (SLA)** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Tracing a Request Against a Latency Budget (SLA)** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Tracing a Request Against a Latency Budget (SLA)** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes