API Load Testing using K6
Load testing is the process of testing an application's performance under various exterme conditions. It helps to identify bottlenecks and issues in time.
In this tutorial, we will show you how to perform API load testing using K6. K6 is an open-source modern load testing tool for developers.
Follow the steps below to get started with load testing using K6:
Installing K6
The first step is to install the K6 package:
For Linux/Debian/UbuntuRun the following four commands one by one:
To install K6 on Windows, open your command prompt and run the following command:
Note: Restart your computer after installation is complete.
For MacOSTo install K6 on MacOS using Homebrew:
To install K6 on Fedora/CentOS, run the following two commands:
Performing API Load Testing
There are four major types of load testing. They are stress testing, smoke testing, soak testing, and load testing.
Stress Testing
Stress test is a type of load testing that helps to determine the limits of the system and verify the stability and reliability of the system under extreme conditions.
Stress testing an API or website is usually done to determine:
- How your system will respond in extreme conditions.
- Maximum capacity of your system to handle users or throughput.
- The breaking point and failure mode of your system.
- If your system will be able to recover without the need for manual intervention once the stress test is finished.
To perform stress testing, do the following:
- Create a JavaScript file with .js extension and add the code as shown in the example below: stress_load_testing.js
import http from "k6/http";
import { sleep } from "k6";
export const options = {
stages: [
{ duration: "2m", target: 100 }, // below normal load
{ duration: "5m", target: 100 },
{ duration: "2m", target: 200 }, // normal load
{ duration: "5m", target: 200 },
{ duration: "2m", target: 300 }, // around the breaking point
{ duration: "5m", target: 300 },
{ duration: "2m", target: 400 }, // beyond the breaking point
{ duration: "5m", target: 400 },
{ duration: "10m", target: 0 }, // scale down. Recovery stage.
],
};
export default function () {
// make sure this is not production url
const BASE_URL = "https://your-api-example.com";
const params = {
headers: {
"Content-Type": "application/json",
},
};
const payload = JSON.stringify({
id: "1",
startDate: "2022-01-01",
endDate: "2022-05-31",
});
const responses = http.batch([
["POST", `${BASE_URL}/search`, payload, params],
["POST", `${BASE_URL}/search`, payload, params],
["POST", `${BASE_URL}/search`, payload, params],
["POST", `${BASE_URL}/search`, payload, params],
]);
sleep(1);
}
Smoke Testing
A smoke test is a standard load test with minimal load. Every time you develop a new script or edit an existing script, you should perform a smoke test as a sanity check.
Smoke testing is usually done to make sure your test script is free of errors and check that your system doesn't throw any errors when under minimal load.
Here's a sample smoke test script that authenticates the user:
smoke_load_testing.js
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
vus: 1, // 1 user looping for 1 minute
duration: "1m",
};
//make sure this is not production url
const BASE_URL = "http://your-api-example.com";
const USERNAME = "developerxyzp";
const PASSWORD = "Password$";
const payload = JSON.stringify({
username: USERNAME,
password: PASSWORD,
});
const header_params = {
headers: {
"Content-Type": "application/json",
},
};
export default () => {
const loginRes = http.post(`${BASE_URL}/users/login`, payload, header_params);
console.log("Login Response : ", loginRes.status);
check(loginRes, { "logged in successfully": (res) => res.status == 200 });
sleep(1);
};
Soak Testing
Soak testing is another type of load testing, which is concerned with a system's reliability over a longer period of time. Soak testing helps to identify performance and reliability issues by putting the system under pressure for a longer period of time.
Bugs, memory leaks, insufficient storage quotas, wrong configuration, and infrastructure failures are all common causes of reliability concerns. Incorrect database tuning, memory leaks, resource leaks, or a big volume of data are all common causes of performance concerns.
A soak test allows you to mimic days of traffic in only a few hours.
Here's an example script for soak testing:
soak_load_testing.js
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 400 }, // ramp up to 400 users
{ duration: '2h56m', target: 400 }, // stay at 400 for ~3 hours
{ duration: '2m', target: 0 }, // scale down. (optional)
],
};
//make sure this is not production url
const API_BASE_URL = 'https://your-api-example.com';
export default function () {
http.batch([
['GET', `${API_BASE_URL}/search/1`],
['GET', `${API_BASE_URL}/search/2`],
['GET', `${API_BASE_URL}/search/3`],
['GET', `${API_BASE_URL}/search/4`],
]);
sleep(1);
}
Load Testing
A load testing is done to determine how a system behaves under normal and peak conditions. The load testing should ensure that a system behaves normally when a large number of users access it at the same time.
Here's an example script for load testing:
load_testing.js
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
stages: [
{ duration: "5m", target: 100 }, // simulate ramp-up of traffic from 1 to 100 users over 5 minutes.
{ duration: "10m", target: 100 }, // stay at 100 users for 10 minutes
{ duration: "5m", target: 0 }, // ramp-down to 0 users
],
thresholds: {
http_req_duration: ["p(99)<1500"], // 99% of requests must complete below 1.5s
},
};
//make sure this is not production url
const API_BASE_URL = "https://your-api-example.com";
const USERNAME = "developerxyzp";
const PASSWORD = "Password$";
export default () => {
const payload = JSON.stringify({
username: USERNAME,
password: PASSWORD,
});
const header_params = {
headers: {
"Content-Type": "application/json",
},
};
const loginRes = http.post(
`${API_BASE_URL}/users/login`,
payload,
header_params
);
check(loginRes, {
"logged in successfully": (resp) => resp.status == 200,
});
sleep(1);
};
Running K6 Test
Run the above .js test file using the K6 command:
The K6 load testing results will look like the following:

Here, checks represents the success rate, http_req_failed shows the proportion of requests that failed, http_reqs shows the total number of requests, and vus shows the number of users.