Writing Test Scripts

k6 tests are written in JavaScript. Here's everything you need to write effective load tests.

The Basics

Every k6 test has two parts: options that configure the test, and a default function that runs once per virtual user iteration.

import http from 'k6/http';

// Options configure the test
export const options = {
  vus: 10,        // 10 virtual users
  duration: '30s', // run for 30 seconds
};

// This runs once per VU iteration
export default function () {
  http.get('https://api.example.com/health');
}

Checks — Assert Responses

Checks validate that responses meet your expectations. They don't stop the test on failure — they track the pass/fail rate so you can set thresholds.

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

export default function () {
  const res = http.get('https://api.example.com/users');
  
  check(res, {
    'status is 200': (r) => r.status === 200,
    'body has users': (r) => JSON.parse(r.body).length > 0,
    'response < 300ms': (r) => r.timings.duration < 300,
  });
}

Thresholds — Pass/Fail Criteria

Thresholds define SLAs. If any threshold is breached, the test fails — perfect for CI/CD integration.

export const options = {
  vus: 50,
  duration: '5m',
  thresholds: {
    // 95% of requests must complete under 500ms
    http_req_duration: ['p(95)<500'],
    // Error rate must be below 1%
    http_req_failed: ['rate<0.01'],
    // 99% of checks must pass
    checks: ['rate>0.99'],
  },
};

Stages — Ramp VUs Over Time

Stages let you gradually increase and decrease load, simulating realistic traffic patterns like ramp-ups and ramp-downs.

export const options = {
  stages: [
    { duration: '1m', target: 20 },   // Warm up to 20 VUs
    { duration: '3m', target: 100 },   // Ramp to 100 VUs
    { duration: '2m', target: 100 },   // Hold at 100 VUs
    { duration: '1m', target: 0 },     // Ramp down to 0
  ],
};

POST Requests with JSON

Send POST, PUT, PATCH, and DELETE requests with custom headers and JSON payloads.

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

export default function () {
  const payload = JSON.stringify({
    name: 'Test User',
    email: 'test@example.com',
  });

  const params = {
    headers: { 'Content-Type': 'application/json' },
  };

  const res = http.post('https://api.example.com/users', payload, params);
  
  check(res, {
    'created': (r) => r.status === 201,
  });
}

Groups — Organize Sequences

Groups let you organize a sequence of requests that represent a user flow, like "browse → add to cart → checkout".

import http from 'k6/http';
import { group, check, sleep } from 'k6';

export default function () {
  group('Browse products', () => {
    const res = http.get('https://shop.example.com/products');
    check(res, { 'listed': (r) => r.status === 200 });
  });

  group('View product', () => {
    const res = http.get('https://shop.example.com/products/1');
    check(res, { 'loaded': (r) => r.status === 200 });
  });

  group('Add to cart', () => {
    const res = http.post('https://shop.example.com/cart', 
      JSON.stringify({ productId: 1, qty: 1 }),
      { headers: { 'Content-Type': 'application/json' } }
    );
    check(res, { 'added': (r) => r.status === 200 });
  });

  sleep(1);
}
loadtest.dev

© 2026 loadtest.dev