← All articles

A bounded local k6 experiment with explicit thresholds

A useful load experiment starts with a scope and a failure criterion. This example performs only a small, local health-endpoint check.

t.Turgay
A bounded local k6 experiment with explicit thresholds

Beginning a load experiment with thousands of virtual users can create a new problem before measuring the intended one. I first define a small experiment and the question it answers. This example, inspired by k6 scripts in my archive, makes a short bounded request sequence against a local health endpoint; it is not a production capacity claim.

Understand the virtual user's workload

The test lasts five seconds with one VU. Each iteration requests the local /health endpoint and sleeps for one second. Use an application you own locally; replacing the target with an arbitrary external service is outside the exercise. Run the file with k6 rather than treating it as an ordinary Node.js HTTP script.

import http from 'k6/http';
import {check,sleep} from 'k6';
export const options={
  vus:1,duration:'5s',
  thresholds:{http_req_failed:['rate<0.01'],http_req_duration:['p(95)<500']}
};
export default function(){
  const response=http.get('http://127.0.0.1:5237/health',{timeout:'2s'});
  check(response,{'status is 200':r=>r.status===200});
  sleep(1);
}

sleep(1) does not promise exactly one request per second. An iteration also includes the request and checks. The short run produces only a small number of observations. A VU describes a concurrent execution flow, not a fixed request rate; a closed workload can slow its own request production as responses become slower.

Checks and thresholds have different responsibilities

The status check records a success or failure in the checks metric. Thresholds define acceptance criteria that can affect the process exit result. This sample has HTTP failure and duration thresholds, but none for checks. A false check alone does not universally mean the run exits unsuccessfully.

To require every check to pass, add a separate threshold to the existing thresholds object:

checks: ['rate==1']

http_req_failed depends on k6's HTTP response-success policy; it does not automatically understand a business success field inside JSON. A 200 response containing an unsuccessful business outcome needs an appropriate content check rather than reliance on the HTTP failure metric alone.

A percentile is not an average

p(95)<500 requires the observed 95th-percentile request duration to remain below 500 ms. Tail values can matter even when the average looks good. However, a few observations from one user over five seconds do not establish a reliable production p95. The example teaches how to express a threshold, not how to certify capacity.

Read the metric definitions as well: http_req_duration is not an interchangeable name for every connection, TLS and end-to-end phase. Compare measurements with the same scope and units rather than attributing every delay to one reported duration.

A fast health endpoint proves a narrow result

A health handler may simply report that the process can respond. It may not exercise database access, login, report generation or article rendering. This experiment checks connectivity and the test setup first. Measuring a business flow needs representative operations, data volumes and user behavior that are not included here.

Make the run reproducible

Record the application version, dataset, resource limits, warm-up conditions and options when comparing runs. A local load generator and application share machine resources. Report the sample count alongside failure rates and percentiles rather than letting a tiny dataset imply broad confidence.

First run with the application available, then use a controlled unavailable local endpoint to verify that the failure threshold can actually fail the test. A test that turns red appropriately is as important as its successful path. More realistic workload choices should follow an understood measurement contract.

k6 threshold behavior; k6 HTTP metric definitions.

✳ You have reached the end of this orbit.
Explore more articles →
turgay.A little code, a few pixels, a lot of curiosity.© 2026 · Made on Earth ✳