You finish a load test, open the aggregate report, and see one number: Average: 820 ms. Looks fine. But some of your users waited four seconds — and the average hides every one of them.
This guide explains what each column in a JMeter report actually tells you, and which numbers are worth reporting to stakeholders.
The example we'll use
Imagine 100 requests to a checkout endpoint (example numbers, for illustration):
| Metric | Value |
|---|---|
| Min | 180 ms |
| Average | 820 ms |
| Median (50th) | 640 ms |
| 90th percentile | 1,450 ms |
| 95th percentile | 2,100 ms |
| 99th percentile | 3,900 ms |
| Max | 7,200 ms |
Same test, seven very different stories. Let's read them one by one.
Average: the number that hides the pain
The average adds up every response time and divides by the count. A few very slow requests pull it up, many fast ones pull it down — so it ends up describing nobody's real experience.
- Two requests at 100 ms and 1,900 ms average 1,000 ms. No user ever waited 1,000 ms.
- Use the average for trends (did it go up between runs?), never for promises to users.
Median (50th percentile): the typical user
Half of all requests were faster than this, half slower. If the median sits far below the average, a slow tail is dragging the average up — and that gap is your first warning sign.
90th percentile: most users
90 out of 100 requests finished within 1,450 ms. 1 in 10 users waited longer. A good everyday health indicator — but on a busy page, 10% is a lot of people.
95th percentile: the usual SLA line
95% of requests were faster than 2,100 ms. This is the most common SLA target because it covers nearly everyone while ignoring rare one-off spikes. It's also why the SLA check in JMeterHub uses the 95% line by default.
99th percentile: your unhappiest regular users
1 in 100 requests took longer than 3,900 ms. That sounds rare, but a user loading a page with 30 requests has a real chance of hitting at least one of them. The 99th percentile is often where problems show up first: garbage collection pauses, lock contention, cold caches, a slow database query.
Rule of thumb: if the 99th is more than 3–4× the median, something is occasionally blocking.
Min: the best case, not the goal
The min tells you how fast the system can be when nothing gets in the way. It's useful for two things:
- Spotting cached responses — an unusually low min may mean you tested the cache, not the app.
- Seeing the floor — if even the min is slow, the problem is in every request (network, heavy payload, slow code path), not just under load.
Max: one bad moment, worth checking
The max is a single request, so never put it in an SLA. But don't ignore it either:
- A max close to your timeout (e.g. 30,000 or 60,000 ms) usually means requests timed out.
- A max that appears only at the peak of the test points to saturation.
- Check when it happened on the response time graph: a single spike is noise, a cluster is a pattern.
Which numbers to report
| Question | Look at |
|---|---|
| What does a typical user see? | Median |
| Are most users OK? | 90th / 95th |
| Did we meet the SLA? | 95th (plus error rate) |
| Is something occasionally blocking? | 99th vs median |
| Did we test the cache? | Min |
| Did anything time out? | Max + errors |
| Is it getting worse between builds? | Average and 95th, compared |
Try it on your own results
Open your .jtl file in the JMeterHub analyzer — it runs entirely in your browser, nothing is uploaded. You get the average, median, 90/95/99th percentiles, min and max per transaction, plus an SLA check with PASS / BREACH badges.
No file handy? Try the Black Friday spike demo and see how far the 99th sits from the average.
Lifetime Pro is free for accounts created before November 27 — saved analyses, PDF reports and AI conclusions included.