About a year ago, I built an internal dashboard to track user engagement across different regions. Product and marketing used it weekly to make decisions. The engagement metric for one region consistently looked lower than the others, and based on that data, it received less attention and investment.
Six months later, someone else on the team looked at the same data and noticed the problem: I had been showing the mean session duration. For that particular region, a small number of power users had extremely long sessions, pulling the mean up. The median — which is what actually represented the typical user — was perfectly healthy. The region had been deprioritised based on a chart that was technically correct but statistically misleading.
That experience is why I now believe statistical thinking is not optional for developers who build things that inform decisions. You do not need a statistics degree. You need to understand a handful of core concepts well enough to know when a number is lying to you.
Mean, Median, and Why the Difference Matters in Practice
The mean (arithmetic average) is sensitive to extreme values. One outlier can pull it far from what most values look like. In the dashboard story above, the mean was technically accurate — it was the correct average — but it was not representative.
The median is the middle value when sorted. For any dataset with outliers or a long tail (and most real-world data has this), the median is a more honest representation of the typical case.
In performance monitoring, this distinction is critical. API response times almost always have outliers — a slow database query, a cache miss, a garbage collection pause. The mean latency looks acceptable because the vast majority of fast requests dilute the slow ones. The median (P50) tells you what the typical user experiences. The P95 and P99 tell you what your unluckiest users experience.
import statistics
# Response times from a real monitoring window (ms)
response_times = [42, 45, 48, 51, 44, 47, 50, 46, 43, 49,
52, 1840, 44, 48, 47, 45, 50, 3200, 46, 44]
response_times_sorted = sorted(response_times)
n = len(response_times_sorted)
mean = statistics.mean(response_times)
median = statistics.median(response_times)
p95_idx = int(n * 0.95)
p99_idx = int(n * 0.99)
print(f"Mean: {mean:.0f}ms") # 286ms — two outliers inflate this
print(f"Median: {median:.0f}ms") # 47ms — what most users actually see
print(f"P95: {response_times_sorted[p95_idx]}ms")
print(f"P99: {response_times_sorted[p99_idx]}ms")
If someone told me the mean response time was 286ms, I would worry. If they told me the median was 47ms, I would feel confident about the typical experience while investigating those two outliers separately. Same data, completely different picture.
Variance and Standard Deviation: Consistency Is a Feature
A system with P50 latency of 100ms is not automatically better than one with P50 of 150ms. What matters is also the spread. A system that is 100ms on average with standard deviation of 5ms is far more predictable than one that is 100ms on average with standard deviation of 300ms. Users experience unpredictability as unreliability, even if the averages match. Standard deviation is the number that tells you about that unpredictability.
Percentiles Are the Right Tool for Performance SLAs
When I write or review SLAs (Service Level Agreements) for services I build, I now insist on percentile-based targets rather than mean-based ones. "P99 latency < 500ms" is a meaningful, testable commitment. "Average latency < 200ms" is easy to satisfy while still having 1% of users wait five seconds on every request.
In a service handling 1,000 requests per second, 1% of requests failing the SLA means 10 users per second with a bad experience. With 1 million daily users, that is 10,000 bad experiences per day — invisible in the mean, visible in the percentiles.
The Law of Large Numbers and Sample Size
One of the most common statistical mistakes I see in engineering teams is drawing conclusions from small samples. A deployment that "seems fine after 10 minutes" has seen perhaps 600 requests at a typical load. At a 0.1% error rate, you expect 0.6 errors — you might see 0 or 1 by chance alone. That tells you almost nothing.
The law of large numbers says that as sample size increases, your measured statistics converge toward the true population statistics. In practice: do not declare a deployment healthy until you have seen enough traffic for the error rate estimate to be reliable. A rough rule of thumb — for a p% error rate, you need at least 1/p samples to see even a single error, and 10/p samples before your estimate is meaningful.
Correlation Is Not Causation — and This Is Not Just a Cliché
I have sat through postmortems where an engineer points at a graph showing two metrics moving together and concludes that one caused the other. Sometimes that is right. Often it is not. Two metrics can correlate because:
- One causes the other
- The other causes the first
- A third variable causes both
- It is a coincidence in the time window you are looking at
Before concluding that a configuration change caused a latency increase, ask: what else changed in that window? Was there a traffic spike? A deployment elsewhere in the stack? A time of day effect? Correlation in observability data is a starting point for investigation, not a conclusion.
What to Actually Apply Day-to-Day
Out of everything above, these are the habits I have found most valuable in daily engineering work:
- Prefer percentiles (P50, P95, P99) over mean for latency and response time metrics
- When you see an average, ask: what does the distribution look like? Are there outliers?
- Do not draw conclusions from n < 100 without acknowledging the uncertainty explicitly
- When two metrics move together, ask "what else changed?" before concluding causation
- Standard deviation is as important as the average when assessing consistency
Statistical thinking does not require you to run formal tests on every data point. It requires you to ask better questions about the numbers in front of you — questions that prevent you from making the kind of mistake I made with that dashboard.
Further Reading
- HdrHistogram — the latency recording tool used by many production monitoring systems, with a good explanation of why percentiles matter
- Khan Academy: Statistics & Probability — the best free introduction I know of, explained visually
- Thinking Statistically by Uri Bram — a short, non-technical book that changed how I think about everyday numbers