CodeRigor

FREE LESSON

Latency distributions & tail evidence

Compute support-aware latency summaries, nearest-rank percentiles and cumulative threshold buckets.

A latency observation needs a boundary and a unit. These fixtures contain nonnegative milliseconds for completed requests; no code sleeps, runs a benchmark or contacts a service. The sample may omit requests, and completion-only logging can exclude timed-out work. The summary therefore describes observed values. It does not establish the latency distribution of all customer requests.

The arithmetic mean is useful for overall cost, but it can conceal the tail. Four observations of 1,1,1,197 ms have mean 50 ms. Most are fast, and one is much slower. A target-success fraction answers how many observations meet a chosen latency boundary. A percentile answers which ordered observation represents a chosen rank under a named convention. Show support alongside both.

A fast mean can hide a slow tail
start / 2
Sorted latencies 1,1,1,197 ms have mean 50 ms, nearest-rank p95 197 ms and a 75% fraction at or below 100 ms.
A fast mean can hide a slow tail
Sorted latencies 1,1,1,197 ms have mean 50 ms, nearest-rank p95 197 ms and a 75% fraction at or below 100 ms.
Python
import math
sample = sorted([197, 1, 1, 1])
q = .95
print(sample[math.ceil(q * len(sample)) - 1])
print(sum(x <= 100 for x in sample) / len(sample))

This course uses nearest-rank: for n>0, rank is ceil(q*n), starting at one, so the Python index is rank minus one. It accepts 0<q<=1. Under this convention p50 of [1,2,3,4] is 2; an interpolating convention could yield 2.5 instead. Neither label alone explains the algorithm. For a twenty-observation sample with nineteen 1 ms requests and one 1000 ms request, nearest-rank p95 is still 1 ms. Inspect the sample and its support before treating a tail label as a complete safety guarantee.

A histogram preserves counts at defined boundaries. In this lab the finite buckets are cumulative: the bucket at 10 ms counts every observation <=10. An observation exactly on a boundary belongs to that bucket. The final implicit +infinity bucket equals the total sample count. Do not add cumulative buckets together, because the same observation contributes repeatedly.

Cumulative buckets retain ties
start / 2
For observations 0,10,20 ms, counts at upper bounds 0,10,20,+infinity are 1,2,3,3. Counts are inclusive and overlap.
Cumulative buckets retain ties
For observations 0,10,20 ms, counts at upper bounds 0,10,20,+infinity are 1,2,3,3. Counts are inclusive and overlap.

Compatible bucket counts can be added across instances before computing an approximate fleet percentile. Individual instance p95 values cannot generally be averaged to recover fleet p95; they discard support and distribution information. The build retains raw observations, so it selects an exact sample rank. It does not reproduce a monitoring backend's histogram interpolation, native histogram implementation or quantile error guarantees.

Empty observations produce count zero and None for mean, percentile and target fraction. Reporting 0 ms would invent a fast request. Reject nonfinite and negative values before sorting; validate quantile and bucket boundaries even when there are no observations. Copy input so a summary does not silently reorder the caller's data.

The checks make rank conventions and inclusive boundaries explicit. Bug hunts expose a dropped bucket tie and a rank/index conversion error. The build handles generators, repeated values, empty bounds and invalid numeric types using only the standard library. Production instrumentation requires a separate decision about timeouts, sampling, measurement boundaries and compatible aggregation.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Use the opening metric overview to place latency summaries among signals. The lesson and Prometheus reading define inclusive buckets, sample support and the exact percentile convention used here.