k6 Load Testing: Complete Getting Started Guide
Load testing tells you how your application behaves under pressure — before real users find out the hard way. k6 is a modern, developer-friendly load testing tool that has quickly become one of the most popular choices for performance testing. This guide walks you through everything you need to get started.
What Is k6?
k6 is an open-source load testing tool built by Grafana Labs. Unlike older tools like JMeter, k6 uses JavaScript (ES6+) for test scripts, making it familiar to most developers. Tests run from the command line, integrate easily into CI/CD pipelines, and output structured metrics.
Key characteristics:
- JavaScript scripting — no XML, no GUI required
- Single binary — easy to install anywhere
- Built-in metrics — response times, error rates, throughput
- CI/CD friendly — exits with non-zero code on threshold failures
- Cloud execution — optional Grafana Cloud integration for distributed tests
Installing k6
macOS:
brew install k6Linux (Debian/Ubuntu):
sudo gpg -k
<span class="hljs-built_in">sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
<span class="hljs-built_in">echo <span class="hljs-string">"deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" <span class="hljs-pipe">| <span class="hljs-built_in">sudo <span class="hljs-built_in">tee /etc/apt/sources.list.d/k6.list
<span class="hljs-built_in">sudo apt-get update
<span class="hljs-built_in">sudo apt-get install k6Docker:
docker pull grafana/k6Verify installation:
k6 versionWriting Your First k6 Script
A k6 script is a JavaScript module with a default export function. k6 calls this function once per virtual user (VU) per iteration.
// hello-k6.js
import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
http.get('https://httpbin.org/get');
sleep(1);
}Run it:
k6 run hello-k6.jsBy default, k6 runs with 1 VU for 1 iteration. You'll see output like:
✓ http_req_duration.............: avg=143ms min=143ms med=143ms max=143ms
http_reqs......................: 1 0.5/sUnderstanding k6 Options
Control the load shape with options:
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
vus: 50, // virtual users
duration: '30s', // how long to run
};
export default function () {
http.get('https://httpbin.org/get');
sleep(1);
}Or pass them via CLI:
k6 run --vus 50 --duration 30s hello-k6.jsTesting Real Endpoints
Here's a more realistic script testing a REST API:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 20,
duration: '60s',
};
const BASE_URL = 'https://api.example.com';
export default function () {
// GET request
const listRes = http.get(`${BASE_URL}/users`);
check(listRes, {
'list status is 200': (r) => r.status === 200,
'list returns array': (r) => JSON.parse(r.body).length > 0,
});
// POST request
const payload = JSON.stringify({
name: 'Test User',
email: `user${__VU}@example.com`,
});
const createRes = http.post(`${BASE_URL}/users`, payload, {
headers: { 'Content-Type': 'application/json' },
});
check(createRes, {
'create status is 201': (r) => r.status === 201,
});
sleep(1);
}The check() function evaluates conditions and tracks pass/fail rates — they don't stop the test, but they appear in the output.
Setting Thresholds
Thresholds define pass/fail criteria for your test. If a threshold is breached, k6 exits with a non-zero code — perfect for CI gates:
export const options = {
vus: 50,
duration: '60s',
thresholds: {
http_req_duration: ['p(95)<500'], // 95% of requests under 500ms
http_req_failed: ['rate<0.01'], // error rate under 1%
checks: ['rate>0.99'], // 99% of checks must pass
},
};Common threshold expressions:
avg<200— average under 200msp(90)<400— 90th percentile under 400msp(99)<1000— 99th percentile under 1 secondrate<0.05— rate below 5%
Ramping Load (Stages)
Instead of flat load, use stages to simulate realistic traffic patterns:
export const options = {
stages: [
{ duration: '30s', target: 10 }, // ramp up to 10 VUs
{ duration: '1m', target: 50 }, // ramp up to 50 VUs
{ duration: '2m', target: 50 }, // hold at 50 VUs
{ duration: '30s', target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'],
},
};Key Metrics
k6 tracks these metrics by default:
| Metric | Description |
|---|---|
http_req_duration |
Total request duration (most important) |
http_req_failed |
Rate of failed requests |
http_reqs |
Total number of requests |
vus |
Active virtual users |
iterations |
Total number of VU iterations |
data_received |
Bytes received |
data_sent |
Bytes sent |
Integrating k6 with CI/CD
GitHub Actions:
name: Load Test
on:
push:
branches: [main]
jobs:
k6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: grafana/setup-k6-action@v1
- name: Run load test
run: k6 run tests/load/api.jsGitLab CI:
load-test:
image: grafana/k6:latest
script:
- k6 run tests/load/api.jsExporting Results
Output results to JSON for further analysis:
k6 run --out json=results.json api.jsOr stream to InfluxDB for Grafana dashboards:
k6 run --out influxdb=http://localhost:8086/k6 api.jsRunning k6 in CI Alongside Functional Tests
HelpMeTest complements k6 for end-to-end functional coverage. While k6 handles load and performance validation, HelpMeTest's AI-powered test automation handles user journey testing — login flows, checkout sequences, form submissions — with continuous 24/7 monitoring.
Use k6 for:
- Performance benchmarking
- Stress and spike testing
- SLA validation in CI
Use HelpMeTest for:
- Functional regression testing
- UI flow verification
- 24/7 uptime and behavior monitoring
Summary
k6 is the modern standard for load testing: JavaScript-based scripts, clean CLI output, threshold-driven pass/fail, and seamless CI/CD integration. Start with a simple script, add checks and thresholds, and graduate to staged load scenarios as you understand your system's behavior under pressure.
Ready to pair load testing with functional coverage? Start with HelpMeTest free — no code required, 10 tests included, monitoring every 5 minutes.