Art of Codeartofcode
LLeeaarrnniinngg
BBlloogg
TToooollss
GGaammeess AArreennaa
JJoobbss
LLiivvee CCoouurrsseess

Courses

  • System DesignHigh-level system design, one everyday scene at a time: 30 concepts and 15 interview rounds.712 lessons
All coursesTutorialsMy Learning

Categories

  • 01AI & Tools
  • 02Tutorials
  • 03Engineering
  • 04Reviews
  • 05Build Logs
  • 06Tales of Misfits
  • 07Opinion
  • 08Career
  • 09News

Read & write

All storiesEvery post, newest first.Write for usPublish your stories and earn from what you write.Writer leaderboardsWho is writing the most read posts.

Categories

  • PDF Tools25
  • Development09
  • Utilities10
  • Design04
  • Converters04
  • Generators02

Featured

JSON FormatterFormat, validate and minify JSON.Regex TesterTest patterns against live text.Merge PDFCombine PDFs in your browser.JWT DecoderRead a token’s header and claims.Password GeneratorStrong passwords, generated locally.Gradient GeneratorBuild CSS gradients visually.
All 53 tools

Play a round

DevdleOne developer word a day, six guesses.Python RushClassic snake, with coding icons to eat.Blink or BreakA quick test of your reflexes.
Games Arena

Learn with us

Live CoursesInstructor-led courses. Join a waitlist and be first in when one starts.LearningStructured programming courses with AI assistance and certificates.

System Design

5. Latency vs Throughput

Lesson 17 of 17

5. Latency vs Throughput

1
The picture to keep in your head
2
5.1 What is latency, exactly?
3
5.2 What is throughput, exactly?
4
5.3 What's the difference between bandwidth and throughput?
5
5.4 Why do averages lie, and what are p50, p95 and p99?
6
5.5 What is tail latency, and why does fan-out make it worse?
7
5.6 What is Little's law?
8
5.7 Where does the time go inside one request?
9
5.8 How do you reduce latency?
10
5.9 How do you increase throughput?
11
5.10 When do latency and throughput fight each other?
12
Memory card and where the analogy breaks
13
Practice: five levels
14
Interview questions
15
Solutions
16
Sources
17
Code lab
5. Latency vs Throughput

Code lab

3 min read+10 XP

Code lab: Chapter 5

The full, tested code for this chapter. Press Run: every check should pass. Then change one number, run it again, and see which check breaks and why.

python

No tracks available

Lofi Player

artofcode

artofcode.in

The den of devs.

Stories, tools, games, and gear for developers.

Read the StoriesEExxpplloorree TToooollss
Art of Codeartofcode

Platform

  • BBlloogg
  • TToooollss
  • GGaammeess AArreennaa
  • CCoouurrsseess
  • LLeeaarrnniinngg
  • CCaammppuuss

Company

  • AAbboouutt UUss
  • JJoobbss && IInntteerrnnsshhiippss
  • CCoonnttaacctt

Legal

  • TTeerrmmss ooff SSeerrvviiccee
  • PPrriivvaaccyy PPoolliiccyy
  • RReeffuunndd PPoolliiccyy

Copyright © 2026 artofcode.in, All Rights Reserved.

IST·--:--

1"""Chapter 5 practice: latency statistics, Little's law, fan-out tail maths and a
2queue simulation (Level 3 Build), and the 'averaging p99s' dashboard bug (Level 4 Debug).
3Standard library only. Run: python3 ch05_latency.py"""
4import math
5import random
6
7
8def percentile(samples, p):
9    """Nearest-rank percentile: the smallest value with at least p% of samples at or below it."""
10    if not samples:
11        raise ValueError("no samples")
12    ordered = sorted(samples)
13    rank = max(1, math.ceil(p / 100 * len(ordered)))
14    return ordered[rank - 1]
15
16
17def summarize(samples):
18    return {
19        "mean": sum(samples) / len(samples),
20        "p50": percentile(samples, 50),
21        "p95": percentile(samples, 95),
22        "p99": percentile(samples, 99),
23        "max": max(samples),
24    }
25
26
27def littles_law(throughput_per_s, latency_s):
28    """L = lambda x W: requests in flight = arrival rate x time each one spends inside."""
29    return throughput_per_s * latency_s
30
31
32def fanout_slow_probability(p_slow, n):
33    """Chance that at least one of n parallel calls is slow, if each is slow with probability p_slow."""
34    return 1 - (1 - p_slow) ** n
35
36
37def simulate_queue(arrival_rate, service_rate, n=200_000, seed=1):
38    """One server, random (Poisson) arrivals, random (exponential) service times.
39    Returns the average time a request spends waiting plus being served."""
40    rng = random.Random(seed)
41    t = 0.0
42    server_free_at = 0.0
43    total = 0.0
44    for _ in range(n):
45        t += rng.expovariate(arrival_rate)
46        start = max(t, server_free_at)
47        server_free_at = start + rng.expovariate(service_rate)
48        total += server_free_at - t
49    return total / n
50
51
52# ---- Level 4: the dashboard bug ---------------------------------------------------------
53
54def make_servers(seed=7):
55    """Ten servers, 1,000 requests each. Nine are healthy; server 9 has a slow disk."""
56    rng = random.Random(seed)
57    servers = []
58    for s in range(10):
59        lat = [rng.uniform(20, 60) for _ in range(1000)]          # healthy: 20-60 ms
60        if s == 9:
61            lat = [rng.uniform(20, 60) if rng.random() > 0.3 else rng.uniform(800, 1200)
62                   for _ in range(1000)]                           # 30% very slow
63        servers.append(lat)
64    return servers
65
66
67def buggy_overall_p99(servers):
68    return sum(percentile(s, 99) for s in servers) / len(servers)  # BUG: averages percentiles
69
70
71def fixed_overall_p99(servers):
72    merged = [x for s in servers for x in s]                       # fix: percentile of all samples
73    return percentile(merged, 99)
74
75
76def run_checks():
77    lat = [10] * 90 + [50] * 9 + [2000]
78    s = summarize(lat)
79    assert s["p50"] == 10 and s["p95"] == 50 and s["p99"] == 50 and s["max"] == 2000
80    assert abs(s["mean"] - 33.5) < 1e-9          # one slow request drags the mean far above p50
81
82    assert littles_law(5000, 0.2) == 1000
83    assert abs(fanout_slow_probability(0.01, 1) - 0.01) < 1e-12
84    assert abs(fanout_slow_probability(0.01, 100) - 0.634) < 0.001
85
86    # Queue maths: average time in system = 1 / (service_rate - arrival_rate).
87    for util in (0.5, 0.9):
88        mu = 100.0
89        lam = util * mu
90        expected = 1 / (mu - lam)
91        got = simulate_queue(lam, mu)
92        assert abs(got - expected) / expected < 0.15, (util, got, expected)
93
94    # Level 4
95    servers = make_servers()
96    bad = buggy_overall_p99(servers)
97    good = fixed_overall_p99(servers)
98    assert good > 3 * bad, (bad, good)
99
100    print(f"All checks pass. Averaged p99s: {bad:.0f} ms. Real p99: {good:.0f} ms.")
101    print(f"Queue at 50% busy: {simulate_queue(50, 100) * 1000:.0f} ms, at 90%: "
102          f"{simulate_queue(90, 100) * 1000:.0f} ms (service time 10 ms).")
103
104
105if __name__ == "__main__":
106    run_checks()