Slide 3 of 9

Reading k6 output

What “good” looks like in the summary

  • Thresholds section shows your gate first; every line should be green before you trust CI with the script.
  • p95 on http_req_duration is stable across two runs at the same profile (small drift is normal; wild swings mean the profile or environment is not ready).
  • http_req_failed stays at zero or inside your agreed budget; mystery 4xx or 5xx under steady load deserve a check or environment fix before you tighten thresholds.
  • Checks reflect a real success condition, not only “HTTP 200.”

Sample k6 terminal output

The block below matches the k6 v1 end-of-test summary layout (thresholds first, then grouped totals). Layout and labels can change between versions; for section order, --summary-mode, and other options, refer to End-of-test summary in the k6 documentation.

text
  █ THRESHOLDS

    http_req_duration
    ✓ 'p(95)<1500' p(95)=148.21ms
    ✓ 'p(90)<2000' p(90)=146.88ms

    http_req_failed
    ✓ 'rate<0.01' rate=0.00%


  █ TOTAL RESULTS

    checks_total.......................: 90      13.122179/s
    checks_succeeded...................: 100.00% 90 out of 90
    checks_failed......................: 0.00%   0 out of 90

    ✓ status is 200
    ✓ body is not empty

    CUSTOM
    custom_waiting_time................: avg=152.355556 min=120      med=141      max=684      p(90)=147.2    p(95)=148.8

    HTTP
    http_req_duration..................: avg=140.36ms   min=119.08ms med=140.96ms max=154.63ms p(90)=146.88ms p(95)=148.21ms
      { expected_response:true }.......: avg=140.36ms   min=119.08ms med=140.96ms max=154.63ms p(90)=146.88ms p(95)=148.21ms
    http_req_failed....................: 0.00%  0 out of 45
    http_reqs..........................: 45     6.56109/s

    EXECUTION
    iteration_duration.................: avg=152.38ms   min=119.37ms med=141.27ms max=684.62ms p(90)=147.11ms p(95)=148.39ms
    iterations.........................: 45     6.56109/s
    vus................................: 1      min=1       max=1
    vus_max............................: 1      min=1       max=1

    NETWORK
    data_received......................: 519 kB 76 kB/s
    data_sent..........................: 4.9 kB 718 B/s

Where to look

Values in the Example column are taken from the sample summary above so the table stays internally consistent.

What you needWhere to find itExample from sample
Latency (p95)http_req_durationp(95)148.21 ms
Throughputhttp_reqs → numeric rate before /s on that line (here 6.56109/s)6.56109/s
Error ratehttp_req_failed → percentage0.00%
Check pass ratechecks_succeeded / checks_total (summary layout varies by version)100.00% (90 of 90)
VU countvus1

Reading threshold results

When thresholds are set, each one shows a verdict:

text
  █ THRESHOLDS

    http_req_duration
    ✓ 'p(95)<1500' p(95)=148.21ms
    ✓ 'p(90)<2000' p(90)=146.88ms

    http_req_failed
    ✓ 'rate<0.01' rate=0.00%

(check mark) means the threshold passed. (X) means the threshold was breached (exit code 99).

What the numbers mean together

Read one run through three lenses. You almost never trust a single number alone.

LensAsk
Latency (p95)Are responses getting slower over time?
ThroughputDoes request rate keep up with how many VUs you added?
CorrectnessAre HTTP failures or check failures climbing?

Four common stories (heuristics for HTTP tests at steady VUs, not guarantees):

If you see…Often means…
p95 steady and low, throughput matches your ramp, errors near zeroThe system looks healthy at this load.
p95 climbs while VUs stay flat and throughput stalls or fallsWork is backing up (responses slower, queueing, or saturation).
Errors or failed checks rise while p95 stays lowAnswers are wrong or rejected even when they arrive fast. Reread checks and response bodies.
Throughput drops with the same VU countEach request is costing more time somewhere (network, app, or dependencies). Pair with http_req_duration trends.

Script

When a k6 test finishes, it prints a summary to the terminal. This slide teaches you how to read it. You’ll see this output after every test run in the learning paths, so understanding it now saves you from guessing later.

The summary has three sections. At the top, you’ll see your checks with pass and fail counts. Below that, the built-in metrics. And at the bottom, thresholds with a check mark or an X for each one.

For latency, look at the HTTP request duration line. k6 reports the average, minimum, median, maximum, the ninetieth percentile, and the ninety-fifth percentile. Ignore the average. It hides outliers. Focus on the ninety-fifth percentile, which tells you the response time that 95 percent of requests were faster than. If your ninety-fifth percentile is 312 milliseconds, only 5 percent of requests took longer.

For throughput, look at the HTTP requests metric. The number after the slash is your requests per second. For error rate, the HTTP request failed metric shows the percentage of requests that k6 counted as failed, including unsuccessful responses from the server.

The check mark or X next to each threshold tells you whether that criterion passed. An X means the threshold was breached, and k6 will exit with code 99. This is the line your continuous integration pipeline cares about.