Definition · Latency under a cacheA request is served in t_hit with probability h and in t_miss with probability 1 − h. Its mean latency is E[latency] = h·t_hit + (1 − h)·t_miss, and its distribution takes only those two values.
t_miss here is the whole miss path: the lookup that failed, the backend call, and the write back into the cache. It is not the backend’s service time alone.
The mean lies strictly between the two latencies whenever h is strictly between 0 and 1, and it equals neither. It sits close to t_hit because h is close to 1: the weighted average is dragged toward whichever outcome is common, and in a cache that is the hit.
Example · A ninety-five per cent cache over a forty-millisecond backendh = 95%, t_hit = 1 ms, t_miss = 40 ms. The mean is (19/20)(1) + (1/20)(40) = 19/20 + 2 = 59/20 = 2.95 ms. The unweighted average of the two latencies is 20.5 ms, seven times too large, and it is the answer you get by forgetting that one outcome happens nineteen times as often as the other.
The percentile is a different question with a different answer
A percentile asks for a value, not an average: the q-quantile is the smallest t with P(latency ≤ t) ≥ q, which is the nearest-rank convention of “Percentiles from a Sample”. Here the function P(latency ≤ t) is a staircase with two steps — it is 0 below t_hit, h from t_hit up to t_miss, and 1 at t_miss and above.
P(latency ≤ t) 1 ┤ ┌──────
│ │
h ┤ ┌─────────────────┘
│ │
0 ┼──────┘
└──────┴─────────────────┴──────
t_hit t_miss
the curve is FLAT at h between the two values, so no percentile
can land between them: q ≤ h → t_hit, q > h → t_miss
At h = 95% that gives p50 = 1 ms, p95 = 1 ms, p99 = 40 ms and p99.9 = 40 ms. The median and the p95 are the hit latency; the p99 is the miss latency, because more than one request in a hundred misses and the hundredth-slowest is one of them.
Where each percentile flips
The q-quantile becomes t_hit at exactly h = q and not before. So the p99 is the miss latency for every hit rate below 99%, and the p99.9 is the miss latency for every hit rate below 99.9%. Improving a cache from 95% to 98.9% does not move the p99 at all, and then one more tenth of a point moves it by 39 ms.
Example · Three hit rates, one tailt_hit = 1 ms, t_miss = 40 ms. At h = 95% the mean is 2.95 ms and the p99 is 40 ms. At h = 99% the mean is 139/100 = 1.39 ms and the p99 has just become 1 ms — but the p99.9 is still 40 ms. At h = 99.9% the mean is 1039/1000 = 1.039 ms and the p99.9 is 1 ms too. The mean moved by under two milliseconds across that whole range; the tail moved in two jumps of thirty-nine.
This is why a cache is a poor answer to a tail problem and a good answer to a throughput problem. It removes work, which is what Hit Rate and Backend Load measured, and it shifts the mean, but the slow requests it leaves behind are exactly as slow as they were. To move the tail you have to move t_miss, or push h past the percentile you care about — and the second of those gets expensive fast, which is what Cache Size and Hit Rate is about.
The model assumes two latencies and one hit rate. A real cache has a spread on each — a hit is 0.8 to 1.4 ms, a miss depends on what the backend was doing — so treat t_hit and t_miss as the typical values and read the answer as a shape rather than a measurement. What survives the simplification is the staircase: two clusters with a gap, and a percentile that lands in one cluster or the other.