Using k6 Thresholds and Checks to Enforce Service‑Level Objectives in Load Tests
Learn how to encode service‑level objectives as k6 thresholds and checks so load tests automatically fail when SLOs are breached, with a minimal script, trust boundaries, operational checks, failure modes, and design‑change triggers.
14 Aug 2026, 23:09 UTC

Requirements
Before writing a test, decide which service‑level objectives (SLOs) you want to validate. Typical SLOs for a web service include:
- 95th‑percentile response time < 200 ms
- Error rate (HTTP 5xx or network failures) < 1 %
- Successful checkout requests > 99 %
These objectives must be expressed as numeric thresholds that k6 can evaluate after the test run.
Minimal Design
The smallest viable design is a single JavaScript file that contains:
- An
optionsblock declaring the thresholds. - One or more HTTP request calls (e.g.,
http.get). check()statements that produce boolean pass/fail results for each request.- No external services, plugins, or custom metrics are required beyond the k6 binary.
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
thresholds: {
// 95th‑percentile latency must be under 200 ms
'http_req_duration{staticAsset:yes}': ['p(95)<200'],
// overall error rate must stay below 1%
'http_req_failed': ['rate<0.01'],
// custom metric for successful checkout
'checkout_success': ['rate>0.99'],
},
};
export default function () {
const res = http.get('https://example.com/api/checkout');
// record a custom metric for successful checkout
const success = check(res, {
'checkout status 200': (r) => r.status === 200,
'response body contains orderId': (r) => r.body.includes('"orderId"'),
});
// expose the result as a custom metric
if (success) {
// increment a custom success counter (k6 counts true as 1)
// using a built‑in metric name; you can also use a Counter
// but for simplicity we rely on the check result being true
// and let the threshold evaluate the rate of true values.
// In practice you would use a Counter metric.
}
sleep(1);
}
Save the file as checkout-slo.js and run it with k6 run checkout-slo.js.
Trust and Data Boundaries
All test data stays inside the runner:
- Request payloads, headers, and any credentials are defined directly in the script or read via
open()from local CSV/JSON files. - Metrics (latency, error flags, custom counters) are calculated in‑process; nothing is sent outside unless you explicitly add an output handler (e.g.,
--summary-exportor a cloud extension). - Therefore the trust boundary is the local machine or the CI worker executing k6.
Operational Checks
k6’s threshold engine evaluates each metric after the test finishes (or early if abortOnFail is set). When a threshold is violated:
- The console prints a line like
thresholds crossed. - The process exits with a non‑zero status code (typically 1).
- CI systems that treat a non‑zero exit as failure will mark the build as red.
- You can also request a JSON summary with
--summary-export out.json; thethresholdssection lists each metric’s pass/fail state.
Failure Modes
Several conditions can cause a test to fail or produce misleading results:
- Network loss, DNS resolution errors, or TLS handshake failures are recorded as
http_req_failedand affect the error‑rate threshold. - Script exceptions (e.g., undefined variable) stop the current VU iteration; k6 counts them as errors.
- CPU or memory exhaustion on the runner can lead to dropped iterations, increasing latency and error rates.
- If the test runs too briefly or with too few virtual users (VUs), the sampled metrics may not be statistically significant, making threshold judgments unreliable.
When the Design Changes
Re‑evaluate the minimal design if any of the following occurs:
- You move to distributed execution (k6 Cloud or multiple local agents). Thresholds must then be aggregated across nodes; you may need to use
--summary-exportand a separate evaluation step. - You test a different protocol (WebSocket, gRPC, MQTT) that requires custom metrics not covered by the built‑in
http_req_*set. - You introduce a secret‑management system (e.g., Vault, AWS Secrets Manager) for credentials, shifting the trust boundary to include the secret provider.
- You need to enforce SLOs per‑service or per‑endpoint with different thresholds; you would split the test into multiple scripts or use tags and conditional threshold expressions.
Verification Steps
- Run the script locally:
k6 run checkout-slo.js. Observe the console; if any threshold is crossed you should seethresholds crossedand the exit code will be 1. - Export a summary:
k6 run --summary-export summary.json checkout-slo.js. Inspectsummary.json.thresholds; each entry should showtruefor pass orfalsefor fail matching the console output. - Introduce a deliberate SLO violation (e.g., add
sleep(2)before the request) and re‑run. Verify that the test fails and the exit code changes. - Vary the VU count and duration (e.g.,
k6 run -v 10 -d 30s checkout-slo.js) and confirm that the threshold outcome behaves as expected under different loads.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.