Skip to content

Anatomy of a load test result

When a MaxoPerf run finishes, the run-detail page is your primary analytical workspace. It presents every signal — throughput, latency percentiles, error breakdown, runner health, and raw logs — across four tabs. This page is a guided tour: we walk through each tab in the order that produces reliable conclusions.

Before you read any chart, look at the header bar. It tells you whether the run is worth analyzing.

The header shows:

  • Test name and run ID — identifies what was tested.
  • Status badgeFinished (clean completion), Failed (failure criterion breached or engine error), Cancelled (stopped by a user). If the status is not Finished, treat the results with caution.
  • Duration — the actual run duration. If this is shorter than you configured, the run was aborted — by a failure criterion, an engine crash, or a manual cancel.
  • VU count — the configured maximum virtual users.
  • Engine badge — Taurus, JMeter, or k6. Relevant when reading logs (engine-specific log format).

The Overview tab is where every analysis starts. It shows the two primary time-series charts (throughput and latency) and the error rate summary.

The throughput chart shows requests per second over the run duration. During a well-formed run:

  • Ramp-up phase: throughput rises from 0 to the plateau.
  • Hold phase: throughput is flat or slightly variable — this is the measurement window.
  • Ramp-down (if configured): throughput drops at the end.

If throughput is lower than expected during the hold phase, the system was the bottleneck — it could not serve requests as fast as the VUs were sending them. If throughput drops partway through the hold, the system degraded under sustained load.

The latency chart shows all four percentile lines over time. Healthy behavior: the lines are relatively flat during the hold phase, with p50 < p90 < p95 < p99 and a consistent gap between them.

Warning patterns:

  • All lines climbing during hold: capacity ceiling — the system is getting slower as the run progresses, often because a shared resource (connection pool, thread pool, database) is becoming more contended.
  • p99 climbing, p50 flat: tail latency issue — a small fraction of requests are slow; the typical request is still fast. Investigate the slow requests in the Errors/Logs tab.
  • Lines diverging after the midpoint: resource exhaustion — GC pressure, file handle limits, or cache eviction starting to bite.

Below the two charts, the Overview tab shows error rate as a percentage and a time-series. A non-zero error rate always deserves investigation before you finalize the result. See the Errors tab for the breakdown.

The Errors tab (also labeled “Log” in some engine configurations) shows every non-successful response grouped by status code, request label, and sample response body.

Each row in the error table represents a distinct error category: a combination of HTTP status code, request label (the named step in your scenario), and error type. The columns you will see:

  • Status code — 4xx (client error: auth, rate limit, bad request) vs 5xx (server error: crash, timeout, overload).
  • Label — which step in your scenario produced this error.
  • Count / rate — how many times and what percentage.
  • Sample body — the actual response the server returned. This is the most diagnostic field.
Status codeLikely causeAction
401 / 403Auth token expired, missing, or wrong scopeCheck test script for token handling
429Rate-limited by the target or a gatewayReduce VU count or add think time
502 / 503Upstream service unavailable or load balancer health check failingCheck system logs; may be real capacity issue
504Gateway timeout — the target took too longCompare to latency chart; likely capacity issue
0 / Connection refusedTarget not reachable or port wrongCheck test configuration and network

The Runners tab shows the health and status of each runner that executed the test. In MaxoPerf, runners are the VMs that generate load.

  • Runner count: matches the expected number for the configured VU count and location count.
  • Status: all runners should be Finished. A runner in Error or Degraded state produced unreliable load during its error window — factor this into your result interpretation.
  • VU distribution: for multi-region tests, confirm VUs were distributed as expected across locations. Imbalanced distribution means the load shape is different from what you configured.
  • Location badges: for multi-region or private-location tests, confirm each runner is from the expected location.

For tests that use multiple managed cloud locations or multiple private locations, the Runners tab shows all runners across all locations. The VU count per runner reflects the distribution MaxoPerf calculated — typically equal shares across locations, but configurable per location.

The Logs tab (or Runner status in some views) shows the raw output from the test engine — Taurus console output, JMeter output, or k6 stderr/stdout. This is the lowest-level diagnostic surface.

When to look at the Logs tab:

  • The run ended early and the header doesn’t explain why.
  • The error table shows Connection refused or unusual error types.
  • You suspect a script problem (wrong URL, malformed request body, assertion that always fails).
  • Engine warnings appear (Taurus warns about misconfigured scenarios; JMeter warns about thread group issues).

Engine logs are engine-specific. Taurus output includes INFO, WARNING, and ERROR level lines. k6 output includes iteration counts and assertion results. JMeter output includes thread group summary rows.

  1. Check the header: status Finished? Duration matches configured? VU count correct?

  2. Overview — throughput: did the run reach the target RPS? Is the hold phase stable or declining?

  3. Overview — latency: is p95 within SLO? Is the p50-to-p99 spread reasonable? Do lines climb during hold?

  4. Overview — error rate: is error rate at or near zero? If not, proceed to Errors tab before conclusions.

  5. Errors tab: what status codes appeared? Which labels? Read a sample body for each non-trivial error.

  6. Runners tab: are all runners Finished? Are VUs distributed as expected? Any degraded runners?

  7. Compare to baseline: if a baseline run exists, load it in the Compare view. Does p95 regress? Does throughput drop?

  8. Record a decision: tag the run (baseline, regression, experiment) and add a note explaining what changed.

DoDon’t
Always check the header status before analyzing charts — a Failed or short run has unreliable data.Immediately jump to the latency chart without confirming the run completed successfully.
Read errors by status code and label — a 401 is a test setup issue; a 503 is a system issue.Treat all errors the same. A 1% error rate of 401s is very different from 1% 503s.
Check the Runners tab to confirm runner health and VU distribution before finalizing results.Assume all runners performed identically — a degraded runner skews the result.
Compare every result to a baseline run before making architectural decisions.Make infrastructure changes based on a single run result without a baseline reference.