Skip to content

API Load Testing with k6 — Scripting, Metrics, and Breakpoint Analysis

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about API Load Testing with k6. We cover key concepts, practical examples, and best practices to help you master this topic.

k6 is a modern load testing tool that uses JavaScript to script API scenarios, simulate virtual users, and collect performance metrics like response time, error rate, and requests per second.

What You'll Learn

  • How to write k6 scripts for API load testing
  • Configuring virtual users, duration, and ramp-up stages
  • Interpreting key performance metrics

Why It Matters

APIs that perform well under light load may fail under production traffic. Load testing identifies bottlenecks, memory leaks, and concurrency issues before they affect users.

Real-World Use

A SaaS platform uses k6 to simulate 1000 concurrent users hitting their REST API. Tests reveal that the database connection pool maxes out at 500 connections, prompting a pool size increase before launch.

flowchart LR
    A[k6 Script] --> B[Virtual Users]
    B --> C[API Under Test]
    C --> D[Metrics Collection]
    D --> E[Threshold Evaluation]
    E --> F[Pass/Breakpoint Report]

Basic Load Test Script

A simple k6 script that tests a GET endpoint with 10 virtual users.

import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  vus: 10,
  duration: "30s",
};

export default function () {
  const res = http.get("https://api.example.com/products");
  check(res, {
    "status is 200": (r) => r.status === 200,
    "response time < 500ms": (r) => r.timings.duration < 500,
  });
  sleep(1);
}

Expected output: k6 reports 100% check pass rate and average response time under 500ms.

Staged Ramp-Up

Gradually increase load to find the system's breaking point.

export const options = {
  stages: [
    { duration: "2m", target: 50 },
    { duration: "3m", target: 100 },
    { duration: "2m", target: 200 },
    { duration: "1m", target: 0 },
  ],
  thresholds: {
    http_req_duration: ["p(95)<2000"],
    http_req_failed: ["rate<0.01"],
  },
};

Expected output: k6 gradually increases to 200 users and reports pass/fail against thresholds.

Testing a POST Endpoint

Load test a POST endpoint that creates resources.

export default function () {
  const payload = JSON.stringify({
    name: `User_${__VU}_${__ITER}`,
    email: `user${__VU}@example.com`,
  });

  const res = http.post("https://api.example.com/users", payload, {
    headers: { "Content-Type": "application/json" },
  });

  check(res, {
    "status is 201": (r) => r.status === 201,
    "response has id": (r) => JSON.parse(r.body).id !== undefined,
  });
}

Expected output: All POST requests return 201 with a unique id.

Common Mistakes

Mistake Why It's Wrong
Testing without ramp-up Immediate high load can trigger false throttling
Ignoring think time Real users pause between actions; without sleep, tests are unrealistic
Running from a single machine Network or machine limits skew results
Not resetting state between iterations Shared state causes cross-iteration contamination
Testing only happy path Edge cases like auth failure or validation errors go untested
Overlooking threshold evaluation Metrics without thresholds have no pass/fail criteria
Not correlating metrics Response time alone doesn't reveal the cause of slowdowns

Practice Questions

  1. What is a virtual user in k6? A: A simulated user that runs the default function in a loop for the test duration.
  2. How do you set a threshold for the 95th percentile response time? A: thresholds: { http_req_duration: ["p(95)<2000"] } — 95% of requests must complete under 2000ms.
  3. What is the difference between vus and stages? A: vus sets a constant user count; stages defines a ramp-up/ramp-down schedule.
  4. How does k6 handle cookies? A: k6 automatically manages cookies like a browser, storing and sending them per VU.
  5. What is the __VU variable? A: A built-in variable that returns the current virtual user number (1-indexed).

Challenge

Write a k6 script that ramps from 0 to 500 users over 5 minutes, holds for 2 minutes, then ramps down. Set thresholds: p(95) response time under 3 seconds and error rate under 0.5%.

FAQ

What is the difference between k6 and JMeter?

k6 is script-based (JavaScript), lightweight, and designed for CI/CD. JMeter is GUI-based and more feature-rich but harder to automate.

Can k6 test Graphql endpoints?

Yes. Send GraphQL queries as POST requests with JSON bodies, just like any HTTP endpoint.

How do you run k6 in CI/CD?

Use the official k6 Docker image (<a href="/devops/prometheus-grafana/">Grafana</a>/k6) in your pipeline and run k6 run script.js.

What metrics does k6 collect?

Key metrics: http_req_duration (response time), http_req_failed (error rate), http_reqs (throughput), vus (active users).

How do you output k6 results?

Use --out json for JSON, --out csv for CSV, or --out influxdb to send to InfluxDB for Grafana dashboards.

What is a breakpoint test?

A test that gradually increases load until the system fails, identifying the maximum capacity.

How do you test authenticated endpoints in k6?

Set auth headers in the default function: http.get(url, { headers: { Authorization: token } }).

Mini Project

Write a k6 test suite for an e-commerce API. Include endpoints: GET /products, POST /cart (add item), DELETE /cart/item, POST /checkout. Use a staged ramp-up from 10 to 200 users over 10 minutes. Set thresholds for response time and error rate. Output results as JSON.

What's Next

Now that you can load test APIs, learn API Security Testing to identify vulnerabilities in your endpoints.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro