Qm
Core

Latency Percentiles and Tail Latency

Why the average response time of a trading system tells you almost nothing about how it actually feels to use, and why quants report latency as percentiles, especially the slow, rare cases in the tail, instead of a single mean.

Prerequisites: Latency vs Throughput

An engineer reports "our order gateway's average latency is 50 microseconds," and a trader shrugs and asks the wrong follow-up question, because average latency almost never determines whether a strategy makes or loses money. What matters is how often the system is slow, because in trading, being slow at the wrong moment, the exact instant a price is about to move, is where the money is lost. A gateway that's fast 999,999 times out of a million and catastrophically slow the one time that matters can lose more than one that's mediocre but consistent every single time.

The fix is to stop summarizing latency with a single number and instead report percentiles: sort every measured latency from fastest to slowest, and the pp-th percentile is the value below which p%p\% of measurements fall. The median (p50p50) is the typical case. The interesting numbers live further out: p99p99 (the slowest 1% starts here), p99.9p99.9, and p99.99p99.99, collectively the tail. A system can have a beautiful median and a nightmarish tail, and the two numbers are close to independent: nothing about a fast median guarantees anything about the tail, because they're typically driven by entirely different causes, a fast median reflects the steady-state hot path, while a bad tail reflects rare events like a garbage collection pause, a cache eviction, an OS scheduling hiccup, or lock contention with another thread.

p50 = 12μs p99 = 90μs p99.9 = 2ms
A typical latency distribution: most requests cluster near the median, but a long right tail means p99 is many times the median, and p99.9 can be orders of magnitude worse still.

Worked example: mean hides the tail

An order gateway logs 100,000 round-trip times. 99,000 of them take 10 microseconds; 900 take 100 microseconds (occasional cache misses); 100 take 5 milliseconds (rare garbage-collection or OS scheduling pauses). The mean is:

xˉ=99,000×10+900×100+100×5000100,000=990,000+90,000+500,000100,000=15.8  μs.\bar{x} = \frac{99{,}000 \times 10 + 900 \times 100 + 100 \times 5000}{100{,}000} = \frac{990{,}000 + 90{,}000 + 500{,}000}{100{,}000} = 15.8 \; \mu s.

That 15.8 μs mean sounds excellent, and it's barely above the 10 μs typical case. But p99p99 sits right at the boundary between the 100 μs and 5 ms groups, roughly 100 μs, and p99.9p99.9 lands inside the 5 ms group entirely. So while the average order takes 15.8 μs, the slowest 1-in-1,000 orders take over 300x longer than typical, a fact the mean completely conceals. If a strategy's edge depends on being fast in exactly the moments the market is moving fastest, precisely when contention and pauses are most likely, the p99.9 number is what determines whether that edge survives, not the mean.

What this means in practice

Latency-sensitive systems are designed and monitored against tail percentiles, not averages: SLAs quote "p99.9 under 200 μs," not "average under 50 μs." Improving the tail usually requires different fixes than improving the median, removing garbage collection, pinning threads to isolated cores, avoiding lock contention, because the tail is caused by rare events the median never touches. Reducing the median while ignoring the tail can make a system look better on a dashboard while actually making its worst-case behavior, the behavior a strategy's risk depends on, no better at all.

Report latency as percentiles, not a single average: the median describes the typical case, but the tail, p99, p99.9, is driven by different causes (GC pauses, contention, scheduling) and is usually what determines real trading outcomes.

A common mistake is optimizing for the mean and assuming the tail improves along with it. The two are close to statistically independent in practice, a change that speeds up the hot path (helping the median) often does nothing for the rare pause that dominates p99.9, and can even make contention-driven tail events worse.

Discussion

Sign in to join the discussion · reading is open to everyone

💡 Discussion rules

  1. Ask and answer about this concept. Off-topic gets removed.
  2. No homework dumps. Show what you tried first.
  3. Corrections are welcome. Cite a source when you claim an error.

Loading discussion…

Related concepts

Practice in interviews

Further reading

  • Gregg, Systems Performance, ch. 2 (Methodology)
ShareTwitterLinkedIn