← All notes

· 2 min read

p95 in an uptime monitor: the nearest-rank method and what it does not hide

How uptime-monitor computes p50/p95 latency and uptime, why the nearest-rank method was chosen, and where those numbers can mislead.

Project: uptime-monitor

The monitor shows p50 and p95 latency of successful checks over 24 hours. The mean is a poor fit here: one outlier shifts it, while the slow tail is exactly what users feel.

Nearest rank

The p-th percentile is the element of the sorted list at rank ceil(p/100 * N). For 20 measurements, p95 is the 19th in ascending order. There is no interpolation: the result is always a real measurement.

rank := int(math.Ceil(p / 100 * float64(len(s))))
return s[rank-1]

The function is pure: the slice is not modified, an empty slice returns 0, and the p<=0 and p>=100 bounds are handled separately. That makes it easy to cover with tests.

Uptime

Uptime is the share of successful checks, ok / total * 100. An important caveat from the README: it is computed from the number of checks, not from durations, so figures for checks with different intervals are not equally precise.

Where the numbers can mislead

  • With few measurements, p95 is almost the maximum.
  • Aggregates run as queries over the raw history: instant for dozens of checks, thousands would need pre-aggregation.
  • Checks run from a single machine; this is not distributed monitoring from several regions.