k6 Load Testing: Complete Getting Started Guide

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 k6

Linux (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 k6

Docker:

docker pull grafana/k6

Verify installation:

k6 version

Writing 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.js

By 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/s

Understanding 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.js

Testing 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 200ms
  • p(90)<400 — 90th percentile under 400ms
  • p(99)<1000 — 99th percentile under 1 second
  • rate<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.js

GitLab CI:

load-test:
  image: grafana/k6:latest
  script:
    - k6 run tests/load/api.js

Exporting Results

Output results to JSON for further analysis:

k6 run --out json=results.json api.js

Or stream to InfluxDB for Grafana dashboards:

k6 run --out influxdb=http://localhost:8086/k6 api.js

Running 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.

Read more