What is a percentile (p50, p95, p99) — and why average response time lies
Your server answers in 300 milliseconds on average. Great number. Meanwhile the support chat says: “everything's slow, I'm waiting five seconds.”
Is someone lying? No. The average is.
Picture a hundred requests. 98 answered in 200 ms. Two took 5 seconds because they hit a cold cache. The average comes out around 300 ms. A pretty number, while two people out of a hundred really did wait five seconds. The average just smeared them across everyone else.
Percentiles were invented to see those people.
What is a percentile, in plain words
A percentile is the line below which a given share of the values falls.
Line up all hundred requests by time, fastest to slowest. Stand at position 95. That request's time is p95: “95% of requests were no slower than this.”
The three percentiles you'll see most:
- p50 — the median. Half faster, half slower. The typical experience.
- p95 — one in twenty. Unlucky, but common.
- p99 — one in a hundred. The tail. The “I'm waiting five seconds” people.
In the example above, p50 = 200 ms and p99 = 5 seconds. Two numbers tell the truth the average hid.
Why the tail matters more than it seems
1% feels small. One user in a hundred, so what. But look at how it works in practice.
A page rarely makes one request. Usually it's dozens: profile, feed, images, counters. Say there are 30, and each has a 1% chance of landing in the slow tail. The chance that at least one of the 30 is slow: 1 − 0.99³⁰ ≈ 26%. One page load in four hits p99.
Google engineers described this in the paper “The Tail at Scale” (2013). Say a server takes longer than a second only 1% of the time. But if a user's request queries 100 such servers at once, 63% of responses will be slow. Rare on one server becomes normal for the whole system.
That's why serious services don't promise “200 ms on average” but “p99 under 500 ms.” Even Google, when it judges site speed for search, looks not at the average but at the 75th percentile of real visitors.
How to calculate a percentile yourself
Sort the values and take the one at the right position. This is the “nearest rank” method, the simplest one:
function percentile(values, p) {
const sorted = [...values].sort((a, b) => a - b)
const i = Math.ceil((p / 100) * sorted.length) - 1
return sorted[Math.max(0, i)]
}
const times = [200, 210, 190, 5000, 205, 198, 4800, 220]
percentile(times, 50) // 205
percentile(times, 95) // 5000
Notice the (a, b) => a - b. Without it, sort compares numbers as text, and 5000 ends up before 600. The percentile comes out wrong — silently, no error.
Where do the values come from? From logs: record each request's time and compute p50 and p99 once a minute. If you use Vercel, Sentry or Grafana, they compute percentiles for you. Look for p95 or p99 next to a chart.
What to do when p99 is bad
Don't guess — look at the slow requests themselves. Log details only for the ones over a second: URL, user, response size. They almost always have something in common. A cold cache after a deploy. One user with a huge list. One heavy endpoint.
Fix the common thing — and the tail gets shorter. “The Tail at Scale” also has a clever trick: if there's no answer after the usual p95 time, send the same request to a second server and take whichever answers first. Load grows by a few percent, while the tail shrinks many times over.
Where you'll meet percentiles
- Server monitoring. API latency is almost always shown as p50/p95/p99.
- AI services. Time to first token jumps around too. The same request sometimes flies, sometimes thinks for a while. We covered why in why AI responses are slow. Watch p95, not your best run.
- Site speed. Search engines' page speed reports are built on the 75th percentile.
- Cloud contracts. Service level agreements say “p99 under N ms.”
Can you average percentiles?
No, and it's a common mistake. The average of 60 per-minute p99s is not the p99 for the hour. A percentile is recomputed from all the raw values for the period. Otherwise one bad hour dissolves among the good ones.
How is the median different from the average?
The average is the sum divided by the count, and one outlier drags it along. The median is the value in the middle of the line, and outliers barely move it. For response times, the median is more honest.
Which percentile should a beginner watch?
Start with two: p50 to see the usual experience, and p95 to see the bad one. p99 becomes useful once you have at least a few hundred requests a minute. With fewer, it jumps around from a single random request.
Short story-lessons, an agent simulator and daily practice — in our mobile app. Free.


