k6 Thresholds: Fail the Build on SLOs
k6 thresholds define SLO pass/fail conditions on metrics; if any is breached, k6 exits with code 99 so CI fails.
Thresholds are how a k6 run becomes a gate. You express the SLO (for example p95 under 500ms, error rate under 1 percent) and k6 turns a breach into a failing build.
What it does
A thresholds object in the script's options maps a metric to one or more pass conditions. If a condition fails at the end of the run, k6 exits non-zero (code 99). With abortOnFail, the run stops as soon as the threshold is crossed.
Common usage
export const options = {
vus: 50, duration: '1m',
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
// stop early if it blows past the limit
'http_req_duration{kind:html}': [
{ threshold: 'p(99)<1500', abortOnFail: true },
],
},
};Options
| Expression | What it does |
|---|---|
| p(95)<500 | 95th percentile under 500ms |
| rate<0.01 | Failure rate under 1 percent |
| avg<200 / med<300 | Average or median bound |
| count<100 | Bound on a counter metric |
| abortOnFail: true | Stop the run on breach (object form) |
| delayAbortEval: '10s' | Wait before evaluating abort |
In CI
Thresholds are the reason k6 belongs in a pipeline: a breached p95 or error rate produces exit code 99 and fails the job automatically, with no extra parsing. Keep the SLOs in the script under version control so changes are reviewed.
Common errors in CI
The job fails with "level=error msg=\"thresholds on metrics 'http_req_duration' have been crossed\"" and k6 exits 99; that is the gate working. If thresholds never trip, the metric name is misspelled or the sub-metric tag (the {kind:html} part) matched nothing. A threshold on a custom metric you never recorded is silently inactive.