k6

A modern load testing tool, using Go and JavaScript

"like unit testing, for performance"

k6 is a modern load testing tool, building on Load Impact's years of experience. It provides a clean, approachable JavaScript scripting API, distributed and cloud execution, and orchestration via a REST API.

Get Started    Documentation

Search results for "{{ search.query }}"

No results found for "{{search.query}}". 
View All Results

Thresholds

What are thresholds?

Thresholds are global pass/fail criteria that you can configure k6 to use, that can act on any result metrics. They are specified in the options section of a k6 script.

Here is a sample script that uses a custom Rate metric together with a threshold to fail the whole load test if more than 10% of requests fail to get a 200-response from the server:

import http from "k6/http";
import { Rate } from "k6/metrics";

var myFailRate = new Rate("failed requests");

export let options = {
	thresholds: {
  	"failed requests": ["rate<0.1"],
  }
};

export default function() {
	let res = http.get("https://loadimpact.com");
	myFailRate.add(res.status != 200);
};

The above threshold specifies that we want our load test to be considered a failure (resulting in k6 exiting with a nonzero exit code) if 10% or more of requests resulted in the server returning anything else than a 200-response. So you specify the pass criteria when defining your threshold, and if that expression evaluates to false at the end of the test, the whole test will be considered a fail.

When executing that script, k6 will output something like this:

threshold.js - executing k6 with a threshold

threshold.js - executing k6 with a threshold

  • In the above case, where the threshold criteria was met, the whole load test is considered to be a pass, which means that k6 will exit with exit code zero.

  • If the threshold had failed, the little green check mark next to the threshold name (failed requests) would have been a red cross instead, and k6 would have generated a non-zero exit code.

Threshold syntax

   export let options = {
      thresholds: {
         metric_name: [ eval1, ... ],
      }
   };

The above declaration inside a k6 script means that there will be a threshold configured for the metric metric_name. To determine if the threshold has failed or passed, the string eval1 will be executed by the javaScript runtime. This means that eval1 should be a valid JavaScript expression.

This JS expression has access to some local variables containing sub-metrics for the "main" metric the threshold is tied to. See Metrics management for a more complete description of different metric types and how they work.

Here is a (slightly contrived) sample script that uses all different types of metrics, and sets different types of thresholds for them:

import http from "k6/http";
import { check } from "k6";
import { Trend, Rate, Counter, Gauge } from "k6/metrics";

export let TrendRTT = new Trend("RTT");
export let RateContentOK = new Rate("Content OK");
export let GaugeContentSize = new Gauge("ContentSize");
export let CounterErrors = new Counter("Errors");

export let options = {
	thresholds: {
    "RTT": [
      "p(99)<300",
      "p(70)<250",
      "avg<200",
      "med<150",
      "min<100",
    ],
    "Content OK": ["rate>0.95"],
    "ContentSize": ["value<4000"],
    "Errors": ["count<100"]
  }
};

export default function() {  
  let res = http.get("https://loadimpact.com");
  let contentOK = res.html("h1").text().includes("Load Impact");
  TrendRTT.add(res.timings.duration);
  RateContentOK.add(contentOK);
  GaugeContentSize.add(res.body.length);
  CounterErrors.add(!contentOK);
};

We have these thresholds:

  • A Trend metrics that gets fed with response time samples, and which has the following threshold criteria:
    • 99th percentile response time must be below 300 ms
    • 70th percentile response time must be below 250 ms
    • Average response time must be below 200 ms
    • Median response time must be below 150 ms
    • Minimum response time must be below 100 ms
  • A Rate metric that keeps track of how often the content returned was OK. This metric has one success criteria: content must have been OK more than 95% of the time.
  • A Gauge metric that contains the latest size of the returned content. The success criteria for this metric is that the returned content must be smaller than 4000 bytes.
  • A Counter metric that keeps track of the total number of times content returned was not OK. The success criteria here is that content can't have been bad more than 99 times.

Failing a load test using checks

Checks are nice for codifying assertions, but unlike thresholds, checks will not affect the exit status of k6. This means a script that only uses checks to verify that things work as expected, will not be able to fail the whole test run based on the results of that/those checks. It can often be useful to combine checks and thresholds, to get the best of both:

import http from "k6/http";
import { check } from "k6";
import { Rate } from "k6/metrics";

export let Rate500 = new Rate("500 errors");

export let options = {
  thresholds: {
  	"500 errors": ["rate<10"],
  }
};

export default function() {
  check(http.get("http://httpbin.org"), {
    "status is 500": (r) => r.status == 500
  }) && Rate500.add(1);   
};

Thresholds