← Blog
guide·30 October 2026·4 min read

Average, 90th, 95th, 99th: what your JMeter response times really say about users

By Mohamed Tarek

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):

MetricValue
Min180 ms
Average820 ms
Median (50th)640 ms
90th percentile1,450 ms
95th percentile2,100 ms
99th percentile3,900 ms
Max7,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

QuestionLook 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.

Related posts