Apdex Calculator

Apdex = (satisfied + tolerating ÷ 2) ÷ total samples, where a request is satisfied if its response time is at most the threshold T, tolerating if it is above T but at most 4T, and frustrated if it is slower than 4T or failed. With T = 500 ms, 8,600 satisfied, 1,000 tolerating and 400 frustrated requests give (8,600 + 500) ÷ 10,000 = 0.91, which rates "Good". The calculator below works from counts or from a pasted list of latencies.
The Apdex formula
Apdex (Application Performance Index) is an open standard that compresses a latency distribution into one number between 0 and 1. You pick one target time T per transaction type, then sort every sample into three buckets:
satisfied : response_time ≤ T
tolerating : T < response_time ≤ 4T
frustrated : response_time > 4T (most tools also count errors here)
Apdex_T = (satisfied + tolerating / 2) / total_samples
The 4T boundary is fixed by the standard; you only choose T. The result is reported with T in brackets, so "0.91 [0.5]" means an Apdex of 0.91 with T = 0.5 seconds. Always quote T alongside the score: 0.91 with T = 2 s and 0.91 with T = 200 ms describe very different services.
Failed requests deserve a decision up front. A fast 500 error is not a satisfied user. Most APM tools count errors as frustrated, and the calculator's latency mode does the same with the "failed requests" field. Do the same in your load test analysis, or a service that fails quickly will score better than one that succeeds slowly.
Apdex rating scale
The standard groups scores into five bands. They are conventions, not laws, but they are what dashboards and reports use:
| Apdex score | Rating | Most frustrated share it allows |
|---|---|---|
| 0.94 – 1.00 | Excellent | 6% |
| 0.85 – 0.93 | Good | 15% |
| 0.70 – 0.84 | Fair | 30% |
| 0.50 – 0.69 | Poor | 50% |
| 0.00 – 0.49 | Unacceptable | more than 50% |
The third column is derived, not part of the standard. It is the worst case: with no tolerating samples, an Apdex of A leaves room for up to 1 − A frustrated requests. An "Excellent" 0.94 can still mean 6 in every 100 requests took longer than 4T or failed.
Worked example from raw latencies
Switch the calculator to latency mode to see the default sample of 20 illustrative response times with T = 500 ms, so 4T = 2,000 ms:
- Satisfied (≤ 500 ms): 15 samples, from 95 ms to 480 ms.
- Tolerating (501–2,000 ms): 520, 640, 700 and 1,900 ms, so 4 samples.
- Frustrated (> 2,000 ms): 2,400 ms, so 1 sample.
- Apdex: (15 + 4 ÷ 2) ÷ 20 = 17 ÷ 20 = 0.85, which is "Good", right on the lower edge.
Add two failed requests in the field below the list and the total becomes 22 with 3 frustrated: (15 + 2) ÷ 22 = 0.77, "Fair". Errors move Apdex quickly, which is one reason to track error rate as a separate threshold as well.
What a given Apdex guarantees about percentiles
Apdex and percentiles are linked. If s, t and f are the satisfied, tolerating and frustrated shares, then Apdex A = s + t/2 and s + t + f = 1. Two bounds follow:
- At least 2A − 1 of requests are satisfied. So p(100 × (2A − 1)) ≤ T.
- At most 1 − A of requests are frustrated. So p(100 × A) ≤ 4T, with errors counted as frustrated.
| Apdex | Guaranteed ≤ T | Guaranteed ≤ 4T |
|---|---|---|
| 0.94 | p88 | p94 |
| 0.90 | p80 | p90 |
| 0.85 | p70 | p85 |
| 0.70 | p40 | p70 |
The practical consequence: Apdex says nothing about p99. A service can score 0.94 while 5% of requests take 30 seconds. If your users or downstream callers care about the tail, keep a p95 or p99 threshold next to Apdex. The p95 vs p99 guide covers which percentile fits which job, and the latency percentile calculator computes them from the same pasted list.
Choosing the threshold T
T should be the response time at which a user stops noticing the wait for that specific operation. Some practical rules:
- One T per transaction type. A search API call and a PDF export should not share a threshold. Blend them and the slow endpoint drags the fast one's score, or the fast one hides the slow one.
- Anchor T to an existing objective. If your SLO says p90 under 300 ms, T = 300 ms makes Apdex and the SLO speak the same language. See SLA vs SLO vs SLI for how those objectives fit together.
- Check your APM's default. Many APM products ship with a default T (often 0.5 seconds for server-side transactions). If production dashboards use that default, use the same T in the load test so the numbers are comparable.
- Do not tune T to make the number look good. Raising T from 500 ms to 1 s will move most services from "Fair" to "Excellent" without a single code change.
Using Apdex as a load test pass/fail threshold
Apdex is a good summary for stakeholders and a weaker gate for automation. It is computed over a whole window, so a 2-minute collapse in a 20-minute run can be diluted to a passing score. Use it like this:
- Pick T from production. Same T as your APM dashboards.
- Compute Apdex per step of the ramp, not only for the whole run. Apdex at 200, 400 and 800 RPS shows where the score drops off; a single number hides the knee. Reading load test results explains how to find that knee.
- Gate on the percentiles Apdex implies. Most load testing tools, LoadTester included, take thresholds as percentiles and error rates rather than Apdex. Apdex ≥ 0.94 at T = 500 ms translates into "p88 ≤ 500 ms and p94 ≤ 2,000 ms including errors", so a practical equivalent is p90 < 500 ms plus p95 < 2,000 ms plus error rate < 1%. In LoadTester you can set those as thresholds with auto-stop, and compute Apdex afterwards from the CSV export.
- Report Apdex with T, sample count and window. "Apdex 0.92 [0.5], 1.1 M samples, steady state at 800 RPS" is a result someone can compare next month.
Use Apdex to tell people how the service felt. Use p95, p99 and error rate to decide whether a build passes. When they disagree, the percentiles are usually telling you about a tail that Apdex averages away.
Common Apdex mistakes
- Leaving errors out. Dropping failed requests from the total inflates the score exactly when the service is in trouble.
- Including warmup. Cold caches and JIT compilation in the first minute drag the score down; exclude the ramp-up from steady-state Apdex, as you would with tail latency numbers.
- Averaging Apdex scores. The mean of two Apdex values is only correct when both have the same sample count. Add the bucket counts, then compute once.
- Comparing scores with different T. Treat a change of T as a new metric.
Checklist
- Choose T per transaction type, matching your APM or SLO.
- Export raw per-request latencies and error counts from the load test.
- Count satisfied, tolerating and frustrated, with errors as frustrated, warmup excluded.
- Compute Apdex per load step and for steady state, and report it as "score [T]".
- Gate the build on p95, p99 and error rate; keep Apdex as the summary line in the load test report.
FAQ
How do you calculate an Apdex score?
Pick a target response time T. Count requests at or under T as satisfied, those above T but at most 4T as tolerating, and those slower than 4T or failed as frustrated. Apdex is (satisfied + tolerating / 2) divided by the total number of samples.
What is a good Apdex score?
On the standard scale, 0.94 to 1.00 is Excellent, 0.85 to 0.93 Good, 0.70 to 0.84 Fair, 0.50 to 0.69 Poor and below 0.50 Unacceptable. A good score only means something together with T, so report it as score plus threshold, for example 0.92 [0.5].
Should errors count in Apdex?
Yes. Count failed requests as frustrated, which is what most APM tools do. If you drop them, a service that fails fast can score better than one that succeeds slowly, and the score improves exactly when users are having the worst experience.
Is Apdex better than p95 or p99 latency?
It answers a different question. Apdex summarizes the share of happy, tolerating and frustrated requests, but an Apdex of A only guarantees that at most 1 - A of requests are frustrated, so it says nothing about p99. Use Apdex as a summary and percentiles plus error rate as pass/fail thresholds.
Can I average Apdex scores from several test runs or servers?
Only if every run has the same number of samples. Otherwise add the satisfied, tolerating and frustrated counts from each source and compute Apdex once from the totals, which gives the correct weighted result.