Skip to content

Interpreting results dos and don'ts

A load test is only as useful as the conclusions you draw from it. Misreading results is common — and often leads teams to ship a “passing” build that hides real performance problems, or to reject a healthy system based on a misleading metric. This page pairs concrete dos and don’ts with the specific MaxoPerf panels where each matters.

The core principle: look at distributions, not point estimates

Section titled “The core principle: look at distributions, not point estimates”

A single number — whether it is the average, the max, or a snapshot RPS — tells you almost nothing about how your system behaves at scale. Load testing is about distributions: how latency is distributed across all requests, how errors are distributed across locations, how throughput is distributed across runners.

  • Do use p95 or p99 as your primary latency SLO anchor. The p95 tells you the worst experience 1 in 20 users has. The p99 covers the worst 1 in 100. These are the numbers that matter for user-facing reliability. In MaxoPerf, the Overview tab shows all four percentile lines (p50, p90, p95, p99) in the latency chart — watch all four.

  • Do compare percentile lines over time (not just end-of-run averages). A rising p99 trend halfway through a soak test often predicts a failure that would not appear in the post-run average. Use the latency time-series chart, not just the summary table.

  • Do set failure criteria on a percentile threshold, not on the average. A failure criterion of p95(http_req_duration) < 500ms is precise. A criterion on the average can be satisfied even when 10 % of users see 2-second responses.

  • Do check the error-rate panel alongside latency. A latency drop during high load is often a sign that slow requests are being dropped (timing out or being load-shed), not that performance improved. Correlate the latency trend with the error rate.

  • Do run long enough to capture a stable steady-state window. The first 2–3 minutes of any run include JVM warm-up, connection pool growth, and CDN cache priming. Do not measure only the first minute. Aim for at least 5–10 minutes of stable load after the ramp-up completes before drawing conclusions.

  • Do verify that your request count is statistically meaningful. A p99 calculated from 100 requests is meaningless — any single outlier dominates it. At 100 VUs with a 1-second think time, a 10-minute run produces ~60,000 requests — that is a meaningful sample. At 5 VUs for 60 seconds, you have ~300 requests — the p99 from that run is noise.

  • Do compare runs against a known baseline. A result in isolation is hard to judge. The comparing runs and baselines recipe shows how to set a baseline run in MaxoPerf and view delta indicators on p95 latency and error rate between the baseline and the current run.

  • Do check the Runners tab during and after every run. Runner saturation — where a runner’s own CPU, memory, or network becomes the bottleneck — produces results that look like application slowness but actually reflect the load-generation infrastructure. Signs of runner saturation include: rising p99 without a matching error rate increase, flat throughput that cannot climb despite increasing VUs, and CPU warnings in the runner health column.

  • Do validate that all configured runners reported healthy. If a runner in a specific region reported errors or went into a degraded state, the results for that region are incomplete. Filter the Overview tab by location to spot per-region anomalies.

  • Do cross-check runner count with your VU target. Each runner has a recommended VU capacity. If you are running 2,000 VUs across 2 runners, each runner carries 1,000 VUs — verify that is within the healthy operating range for your configuration.

  • Don’t use the average (mean) latency as your headline SLO metric. The average is pulled down by the majority of fast requests and hides the tail. A p50 of 80 ms average can coexist with a p99 of 3,000 ms. See Latency percentiles deep dive.

  • Don’t judge a test by the minimum latency. The minimum almost always reflects a cache hit or a single lucky request. It tells you nothing about typical user experience.

  • Don’t compare two runs if their load profiles differ. A run at 100 VUs and a run at 500 VUs are not comparable. Set the same profile, same ramp, same duration, and the same think time before declaring a regression or improvement.

  • Don’t measure only the ramp-up period. During ramp-up, VU count is climbing and results are biased low. Wait for the steady-state plateau, then measure.

  • Don’t run a soak test for less than an hour. Memory leaks, connection pool exhaustion, and log file growth are slow-burn problems. A 10-minute run will not surface them. The overnight soak test recipe recommends a minimum 8-hour window.

  • Don’t declare a “pass” because the test finished without errors. A test with 0 errors at 10 VUs tells you nothing about behaviour at 500 VUs. Make sure your load level is representative of the target you are testing against.

  • Don’t report runner-saturated results as application results. If your Runners tab shows a runner in a degraded or warning state, re-run with fewer VUs per runner before drawing conclusions. Reduce the VU count or add more runners.

  • Don’t ignore the Runners tab just because the test finished. Runners can be quietly saturated without surfacing explicit errors. Check CPU and memory indicators for every runner, especially on high-VU or long-duration tests.

SignalWhere in MaxoPerfWhat to look for
p50 / p95 / p99 latencyOverview tab → Latency chartRising trend, diverging percentile lines
Error rateOverview tab → Error rate panelNon-zero rate, spikes coinciding with VU increases
Throughput (RPS)Overview tab → Throughput chartPlateau or drop that does not match VU count
Runner healthRunners tabDegraded/Error state, CPU/memory warnings
Per-location resultsOverview tab → Location filterRegional outliers
Request-level errorsLog tabSpecific status codes, messages, URLs