Glossary · P

Percentile (p95, p99)

A value below which a given share of observations falls, e.g. p99 latency: 99% of requests are at least this fast.

By Obseria Editorial TeamUpdated

Definition

A percentile is the value below which a given percentage of observations fall. In observability, p95 or p99 latency means 95 or 99 percent of requests completed at or below that duration. Percentiles reveal tail behavior that averages hide, which is why SLOs and latency alerts are usually defined on them.

What is a percentile?

A percentile ranks observations and reports the value at a given position. The 50th percentile (p50, the median) splits requests into a faster and a slower half. The 99th percentile (p99) is the duration that 99 percent of requests stay at or below; only the slowest 1 percent are slower. In monitoring, percentiles are almost always applied to latency, but they work for any distribution: payload sizes, queue wait times or page load times in real user monitoring.

The common shorthand is p50, p90, p95, p99 and p99.9. The further you go into the tail, the more data you need for a stable value: a p99.9 computed from 200 requests is just the slowest request.

How percentiles are calculated

For a set of n sorted values, the nearest-rank method takes the value at rank ceil(p / 100 × n). For 1,000 requests, p99 is the 990th fastest request and p50 is the 500th. Other methods interpolate between neighboring ranks, so tools can report slightly different numbers for the same data.

Storing every raw value does not scale, so monitoring systems estimate percentiles from histograms. A histogram counts observations per bucket (for example 0 to 100 ms, 100 to 250 ms, 250 to 500 ms). Prometheus histogram_quantile() finds the bucket that contains the target rank and interpolates linearly inside it, so the accuracy depends on bucket boundaries. OpenTelemetry exponential histograms use automatically scaled buckets and keep the relative error small without manual tuning.

Why averages mislead

Latency distributions are skewed: most requests are fast, a few are very slow. The mean mixes both groups into a number that describes almost nobody. Consider this illustrative set of 1,000 requests:

RequestsDuration
90080 ms
90400 ms
103,000 ms

The mean is (900 × 80 + 90 × 400 + 10 × 3,000) / 1,000 = 138 ms, which looks healthy. The percentiles tell a different story: p50 = 80 ms, p95 = 400 ms, p99 = 400 ms and p99.9 = 3,000 ms. One request in ten is five times slower than the median, and one in a hundred takes three seconds. Those are the users who abandon a checkout.

Tail latency amplifies with fan-out

When a single page or API call depends on many backend requests, the slow tail becomes the norm. If a page makes 100 independent backend calls, each with a 1 percent chance of hitting p99 latency, the probability that at least one call is that slow is 1 − 0.99 to the power of 100, roughly 63 percent. The backend's p99 becomes the user's typical experience.

Aggregation rules you must know

  • Never average percentiles. The mean of p99 values from ten pods is not the p99 of the service. A pod with little traffic counts as much as a busy one, and the math does not hold even with equal traffic.
  • Aggregate histograms, then compute. Sum bucket counts across instances first, then derive the percentile. This is why histograms beat client-side summaries.
  • Mind the window. A p99 over five minutes and a p99 over 30 days answer different questions. SLOs usually count good versus total events over the full window instead of averaging short-window percentiles.

Best practices

  1. Track at least p50, p95 and p99 per endpoint, plus the request rate so you know how many users a percentile represents.
  2. Define SLOs as threshold ratios, such as "99 percent of requests faster than 300 ms", which are easy to aggregate and explain.
  3. Place histogram bucket boundaries around your SLO thresholds, or use exponential histograms.
  4. Split percentiles by meaningful dimensions such as route, region or customer tier, but keep cardinality bounded.
  5. Use exemplars to jump from a slow bucket straight to a representative trace.

Common mistakes

  • Alerting on average latency and missing regressions that only affect the tail.
  • Reporting p99.9 from low-traffic endpoints, where one request decides the value.
  • Comparing percentiles from tools that use different calculation or interpolation methods.
  • Excluding errors or timeouts from latency data, which makes the tail look better than it is.

How Obseria helps

Obseria stores latency as histograms, including OpenTelemetry exponential histograms, so p50 to p99.9 can be computed and aggregated correctly across any dimension at query time. Percentile charts link to the underlying traces in distributed tracing, and Obseria Intelligence learns a baseline per endpoint to flag tail-latency regressions before they consume your error budget.

Frequently asked questions

p99 latency is the duration that 99 percent of requests meet or beat. Only the slowest 1 percent of requests take longer. It is a common basis for latency SLOs and alerts because it captures the experience of the slowest users.

No. p50 is the median, the middle value of the sorted data. The average is the sum divided by the count and is pulled up by a few slow outliers, so in skewed latency data the average is usually higher than the median.

No. Averaging percentiles gives a number without statistical meaning. Combine the underlying histograms by summing bucket counts across servers, then compute the percentile from the merged histogram.

Use both for different purposes. p95 is stable and good for trend dashboards, p99 shows tail problems that affect a meaningful number of users at scale. For very high-traffic services, p99.9 can be worth tracking as well.

Put these concepts into practice

Try Obseria free for 14 days, with OpenTelemetry and no proprietary agents.