Lesson 2 · Predict → Run → Prove
You can predict the mean perfectly and still be blind to what your users feel. This lesson is about learning to distrust it.
In Lesson 1 you found the ceiling: ~25–30 req/s, no matter how much load you offer. Here's the obvious next question — if extra load doesn't become throughput, where does it go? The answer is written in the latency percentiles, and it is invisible to the one number most dashboards lead with.
Every response time splits in two:
response time = service time + queue wait
(~50 ms, fixed) (grows with backlog)Below the ceiling there's no backlog, so latency ≈ service time and everyone's experience is the same. Above the ceiling, requests pile up behind the three workers, and the wait lands on the unlucky requests first. The distribution goes bimodal: some served immediately, some stuck behind the queue. And the mean of a bimodal split is a lie — it reports a middle nobody actually experiences.
| Offered load | Throughput | p50 | mean | p99 |
|---|---|---|---|---|
| c = 1 (baseline) | 16 req/s | 61 ms | 62 ms | 76 ms |
| c = 4 (at the knee) | 25 req/s | 165 ms | 158 ms | 248 ms |
| c = 20 (5× the load) | 25 req/s | 255 ms | 773 ms | 17,521 ms |
Going from c=4 to c=20 you offered five times the load. Two predictions:
Drive load while watching the latency panel. Any load tool works — the percentiles come from the server-side histogram, so even the curl fallback shows them on Grafana:
cd ~/Desktop/thread-starvation-course/demo
./run-app.sh broken 4 # if not already running
python3 loadp.py 4 20 # knee: p99 close to p50
python3 loadp.py 20 25 # overload: watch p99 detonate
# (or ./load.sh 20 25 — drives load; read percentiles off Grafana)
Open Grafana :3000 → Row 1. Put p50 and p99 on the same panel and watch the gap open as you step the load up. The throughput panel beside it stays flat. That side-by-side — flat throughput, diverging percentiles — is the picture to burn in.
Throughput held flat at 25 req/s from c=4 to c=20, yet p99 leapt from 248 ms to 17,521 ms. Where did the five-fold extra load actually go?
L = λW. The same equation that predicts the ceiling (Lesson 1) predicts the mean latency here. It says nothing about the tail — which is precisely why the tail needs its own panel. For the deeper "why percentiles, not averages" argument, Gil Tene's talk "How NOT to Measure Latency" is the canonical reference.