📊 SRE

API Latency Percentile Calculator

Enter response times (one per line, in ms) to calculate P50, P90, P95, P99, P99.9 percentiles with a latency histogram. Essential for SLA planning and performance monitoring.

📖 How to Use
1
Paste response times in milliseconds — one per line
2
P50, P90, P95, P99 percentiles calculate automatically
3
View the histogram to see the latency distribution shape
📝 Examples
Healthy API
12, 15, 18, 22, 25, 14, 16, 45, 120, 8
P50: 16ms, P95: 82ms, P99: 120ms
📝 Response Times (ms, one per line)

How Averaged Latency Hides the Requests That Matter

Average response time is a metric that behaves reasonably right up until the moment it doesn't, and the failure mode is structural rather than a one-off glitch: an average collapses every sample into a single number by treating a request that took 40ms and a request that took 8 seconds as equally weighted data points, so a small fraction of genuinely bad requests gets diluted into invisibility by the much larger mass of fast ones surrounding them. A service can sit at a healthy-looking average for weeks while a consistent slice of its traffic takes twenty times longer than typical, and that slice is often exactly the traffic that generates support tickets, abandoned checkouts, or timeout-triggered retries elsewhere in the system — none of which shows up as a dip in the average, because the arithmetic is doing precisely what it's designed to do: smooth that variance away. This is why an SLA built on average latency systematically understates user pain, and why the fix isn't a better average, it's a different statistic entirely: computing percentiles from the sorted distribution rather than summing and dividing lets P50, P95, and P99 each answer a different question — the typical case, the bad case, and the worst case a meaningful share of users actually experience — without one number trying and failing to answer all three at once.

Percentiles, Averages, and the Number Nobody Should Trust

An average collapses an entire distribution into one number by treating every sample as equally informative, which is precisely the wrong assumption for latency data: a handful of very slow outliers get diluted into invisibility by the mass of fast requests around them, so the average systematically understates how bad the worst experiences actually are. The maximum has the opposite problem — a single garbage-collection pause or one cold-start request can produce a max that's ten times worse than anything a typical user will ever see, making it too noisy and unstable to build an SLA around. Percentiles sit between these two failure modes by design: P50 describes the median experience, P95 and P99 describe what your worst-treated users actually encounter, and because they're computed from the sorted distribution rather than summed and divided, a single extreme outlier can't distort the P50 or P90 the way it distorts an average.

Handling Real Latency Data With Care

Response-time samples are usually safe to paste as raw numbers, since a duration in milliseconds carries no identifying information on its own — but the surrounding context engineers paste alongside them sometimes does. A CSV exported straight from an APM tool can carry a request-ID, user-ID, or full URL column next to the duration column, and pasting that whole export into any browser-based tool — this one included — puts those identifiers into browser history and any screen-share happening at the time. This tool only needs the bare numeric values to compute percentiles correctly, so the safer habit is to strip everything but the duration column before pasting, the same discipline you'd apply before attaching a log excerpt to an external support ticket.

Getting the Same Numbers From a Terminal

The calculation this tool performs — sort the samples, then linearly interpolate at position (P/100) × (N-1) in the sorted array — is the identical algorithm behind NumPy's percentile() function, so a Python one-liner like python3 -c "import numpy as np; print(np.percentile(data, 99))" against the same dataset will reproduce this tool's P99 exactly. On the command line without Python available, awk or sort -n piped through a small script can approximate the same result for a quick check. At the infrastructure layer, Prometheus's histogram_quantile() function computes percentiles from pre-bucketed histogram data rather than raw samples, which scales to millions of requests per second but trades away exact precision for bucket-boundary approximation — this tool is for the exact, small-to-medium-sample calculation you'd do with a CSV of raw request durations pulled from a load test or an incident window, not for querying a live time-series database.

Frequently Asked Questions

What is P99 latency?

P99 (99th percentile) latency means that 99% of requests complete faster than this value — or equivalently, only 1 in 100 requests takes longer. If your P99 is 500ms, then the slowest 1% of requests each take more than 500ms. P99 is the industry standard metric for API performance SLAs because it captures tail latency: the worst-case experience that your slowest users encounter. Using the average instead of P99 can dramatically underestimate how slow the experience feels for real users during traffic spikes or contention events.

What is the difference between P50 and P99?

P50 (the median) represents the typical user experience — exactly half of all requests are faster and half are slower. P99 represents the worst-case experience for the slowest 1% of users. A healthy, well-optimized API has a small ratio between P50 and P99; a ratio of 2x to 5x is common for database-backed APIs. A very large gap — for example P50=20ms and P99=2000ms — almost always indicates an intermittent problem: database connection pool exhaustion, garbage collection pauses, lock contention, or cold cache misses that hit only occasionally but very hard when they do.

What is a healthy P99 latency for a REST API?

A healthy P99 depends heavily on the type of operation. For read-only endpoints backed by an in-memory cache or Redis, P99 under 50ms is achievable and expected. For database-backed read queries on tables of reasonable size, P99 under 200ms is a common target. For write operations that involve database transactions, email sending, or external API calls, P99 under 500ms is generally acceptable. Any synchronous user-facing endpoint with P99 above 1 second warrants immediate investigation. The P50-to-P99 ratio is often more informative than the absolute number: a large ratio signals that something is failing intermittently.