K6 (used for API load testing) on backend

📄 Table of Contents

  • Introduction to K6
  • basic K6 example sample
  • basic http.get & http.post requests
  • handleSummary in k6
  • checks in k6
  • Data Parameterization in K6
  • Testing k6 using stages
  • How to run a single test once?
  • When parameterizing data, how do I not use the same data more than once in a test?

▬▬▬▬▬▬▬▬▬▬▬▬▬▬ ✦ ✦ ✦ ▬▬▬▬▬▬▬▬▬▬▬▬▬▬

K6- open source load testing tool

K6 — formerly known as Load Impact

k6 version — to get version installed and k6 help

written in GO language as backend but users can write the scripts using Javascript.

k6 run script_1.js

http_req_duration is the most important one.

basic K6 example: script_1.js

Customize with handleSummary()

Use the handleSummary() function to completely customize the end-of-test summary report.

k6 callshandleSummary() at the end of the test run, even after teardown(). If handleSummary() is exported, k6 does NOT print the default summary.

Besides customizing the CLI summary, you can also transform the summary data into machine- or human-readable formats. This lets you create JS-helper functions that generate JSON, CSV, XML (JUnit/xUnit/etc.), HTML, etc. files from the summary data.


Checks are like assertions, but they don’t halt execution. Instead, they store the result of the check, pass or fail, and let the script continue. If you want to halt execution, take a look at thresholds (which can include checks).

For more on checks do read @ https://k6.io/docs/using-k6/checks/

Data Parameterization

Scripting examples on how to parameterize data in a test script. Parameterization is typically necessary when Virtual Users (VUs) will make a POST, PUT, or PATCH request in a test.

Parameterization helps to prevent server-side caching from impacting your load test.

For more on Data Parameterization read @ https://k6.io/docs/examples/data-parameterization/

Performance Testing your web app with k6

Watch out @ https://www.youtube.com/watch?v=Hu1K2ZGJ_K4 for more below:

for more watch @ https://www.youtube.com/watch?v=xJLABpaYllM

Counter Metrics
Checks in K6
Thresholds Matrics
Anatomy of a test in K6
Recording Tests in K6

End-of-test summary

When a test finishes, k6 prints an end-of-test summary to stdout, providing top-level details about the test run.

If the default report doesn’t suit you, you can use the handleSummary() function to completely customize output (including format).

return {          stdout: textSummary(data, { indent: “ “, enableColors: true }),};


k6 extension for writing files, implemented using the xk6 system.


xk6 build v0.36.0 --with github.com/avitalique/xk6-file@latest


import file from 'k6/x/file';const filepath = 'sample-output.txt';export default function () {
file.writeString(filepath, 'New file. First line.\n');
file.appendString(filepath, `Second line. VU: ${__VU} - ITER: ${__ITER}`);

Run sample script

./k6 run sample-script.js

Testing k6 using stages

For example, you want to start with some number of users for x amount of time.

Then you want to increase your load for some x amount of time gradually. This way you can load test your application under different scenarios.

You can see a nice graph as well if you are testing your endpoint in different stages. Let’s look at how we can do this using k6:

import{ sleep } from 'k6';
import http from 'k6/http';

export let options = {
homePage: {
executor: 'ramping-vus',
preAllocatedVUs: 10,
startVUs: 3,
stages: [
{ target: 20, duration: '30s' },
// linearly go from 3 VUs to 20 VUs for 30s
{ target: 100, duration: '0' },
// instantly jump to 100 VUs
{ target: 100, duration: '10m' },
// continue with 100 VUs for 10 minutes

export default function() {

In above example, we have set some option. We are testing our home page we will start with 3 virtual users first. Next, we will linearly go from 3 virutual users to 20 virtual users for next 30s.

Again, we would like to see a big spike therefore we are instantly jump from 20 virtual users to 100 virtual users in no time.

We would then like to see 100 virtual users for next 10 minutes. If you are to draw a chart for above script you will see something like this:

Now, run above script to see the results on your terminal:

How to run a single test once?

By default, unless you specify any of the options to configure number of users, stages, etc., k6 will execute one iteration of your test script using one virtual user.

You could also explicitly define those options:

export let options = {
vus: 1,
iterations: 1

When parameterizing data, how do I not use the same data more than once in a test?

read more @ https://community.k6.io/t/when-parameterizing-data-how-do-i-not-use-the-same-data-more-than-once-in-a-test/42

As mentioned above, in order to prevent collisions between VUs accessing data from an external source, we need to calculate a unique number per VU iteration. Luckily, we have a few pieces of data we can use to calculate this. k6 provides the ID of VUs per load generator(k6 instance) as well as an iteration for each VU.

__VU is the ID of a VU. It is 1 based and assigned sequentially as VUs ramp up. Every VU on a load generator will have a unique VU ID.
__ITER is 0 based and increases sequentially as the default function is completed by VUs. Every VU will have their own iteration count.

Consider this example, with my script uniqueNum.js:

import http from "k6/http";
import { sleep } from "k6";
export default function() {
console.log(`VU: ${__VU} - ITER: ${__ITER}`);
let uniqueNumber = __VU * 100 + __ITER -100 ;

If I run the above script k6 run uniqueNum.js -i 10 -u 10 I will see in the console that each VU will start logging unique numbers in my console window, separated be 100. Resulting in no collisions. I can use this number to select a position from an external file.

// Separate file where contents of data.json follows this pattern:
"users": [
{ username: "test", password: "qwerty" },
{ username: "test", password: "qwerty" }

Then, if our script looked something like:

const data = JSON.parse(open("./data.json"));export default function() {
let uniqueNumber = __VU * 100 + __ITER;
let user = data.users[uniqueNumber];

We are now accessing a unique position per iteration and per virtual user.

Some things to keep in mind regarding the above method:

  • In our calculation of uniqueNumber, 100 would be the maximum iterations VUs can make before collisions. My selection of it was arbitrary here, you can decrease it or increase it based on need. You may know your test will never exceed 20 iterations per VU
  • The higher the above number, the larger your source file must be. A test with 200 VUs would need 20k lines/rows of unique data if all iterations were completed
  • In the Load Impact Cloud, a maximum of 200 VUs are assigned per load generator. So you would need to take LI_INSTANCE_ID into account when calculating unique values. More info on Load Impact env variables her

Apache JMeter

for more watch @ https://www.youtube.com/watch?v=BtlzKxsZzVU





Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Anil Kumar

Anil Kumar

Experience with Front-end Technologies and MERN / MEAN Stack. Working on all Major UI Frameworks like React, Angular.