Skip to content

Instantly share code, notes, and snippets.

@potikanond
Last active September 26, 2025 02:11
Show Gist options
  • Save potikanond/5718fec2183016e270cc4ba97449ce08 to your computer and use it in GitHub Desktop.
Save potikanond/5718fec2183016e270cc4ba97449ce08 to your computer and use it in GitHub Desktop.
26x494 : K6 Load Testing Tutorial

Full Stack Dev: K6 Load Testing Tutorial

Setup K6

Install K6 for Windows

  • Winget: winget install k6
  • Download from official website k6.io

Writing your K6 scripts

Step 1: Simple Test

Let's create your first test script src/k6/load_test.js.

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

export default function () {
  http.get("https://test.k6.io");
  sleep(1);
}

This script performs an HTTP GET request to https://test.k6.io and then pauses for 1 second before repeating the process.

You can now run the test by using this command:

k6 run src/k6/load_test.js

You can also update your package.json by adding the following line in the scripts section.

"scripts": {
    ...

    "load-test": "k6 run src/k6/load_test.js",
    "load-test-reports": "k6 run --out json=report.json src/k6/load_test.js && k6 report --reporter=html=report.html report.json",
    "load-test-csv": "k6 run --out csv=report.csv src/k6/load_test.js"
  }

And now you can run your test using command:

pnpm run load-test

Step 2: Specify Virtual Users and Duration

You can specify the number of VUs (Virtual Users) and the duration of the test to simulate real users accessing your application:

k6 run --vus 10 --duration 15s load_test.js

This command runs the test with 10 VUs for 15 seconds.

or we can update the src/k6/load_test.js by adding options:

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

export const options = {
  vus: 10,          // number of virtual users
  duration: "15s",  // duration of the test
};

export default function () {
  ...
}

Step 3: Testing Complex Scenarios

You can create more complex testing scenarios where the number of users ramps up, holds steady, and then ramps down.

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

export let options = {
  stages: [
    { duration: "10s", target: 20 }, // Ramp-up to 20 VUs
    { duration: "20s", target: 20 }, // Stay at 20 VUs for 1 minute
    { duration: "10s", target: 0 }, // Ramp-down to 0 VUs
  ],
};

export default function () {
  let res = http.get("https://test.k6.io");
  check(res, {
    "status is 200": (r) => r.status === 200,
  });
  sleep(1);
}

Step 4: Custom Metrics and Thresholding

You can create custom metrics to gather specific performance data.

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

let myTrend = new Trend("my_trend");

export let options = {
  stages: [
    { duration: "10s", target: 20 },
    { duration: "10s", target: 20 },
    { duration: "10s", target: 0 },
  ],
  thresholds: {
    http_req_duration: ["p(95)<500"], // 95% of requests must complete below 500ms
    my_trend: ["avg<200"], // Custom threshold for the custom metric
  },
};

export default function () {
  let res = http.get("https://test.k6.io");
  check(res, {
    "status is 200": (r) => r.status === 200,
  });
  myTrend.add(res.timings.duration);
  sleep(1);
}

This script does the following:

  • Defines a custom metric my_trend.
  • Sets thresholds for HTTP request duration and the custom metric.
  • Adds the response time to the custom metric.

Step 5: Simulate User Behaviors

Testing multiple API endpoints and simulates different user behaviors

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

export let options = {
  stages: [
    { duration: "10s", target: 20 },
    { duration: "20s", target: 20 },
    { duration: "10s", target: 0 },
  ],
};

export default function () {
  group("Public endpoints", function () {
    let res = http.get("https://test.k6.io/public/crocodiles/1/");
    check(res, { "status is 200": (r) => r.status === 200 });
    sleep(1);

    res = http.get("https://test.k6.io/public/crocodiles/");
    check(res, { "status is 200": (r) => r.status === 200 });
    sleep(1);
  });

  group("Private endpoints", function () {
    let loginRes = http.post("https://test.k6.io/auth/token/login/", {
      username: "test",
      password: "test",
    });

    check(loginRes, { "login status is 200": (r) => r.status === 200 });

    let authHeaders = {
      headers: {
        Authorization: `Bearer ${loginRes.json("access")}`,
      },
    };

    let res = http.get("https://test.k6.io/my/crocodiles/", authHeaders);
    check(res, { "status is 200": (r) => r.status === 200 });
    sleep(1);
  });
}

This script tests both public and private endpoints, simulating different user behaviors.


Run InfluxDB

docker run -dp 8086:8086 -v influx_data:/varlib/influxdb2 --name influxdb influxdb:2.7

After the container starts, access the InfluxDB UI at http://localhost:8086 and complete the initial setup

  • creating an organization, user, and bucket

or create influx-compose.yml:

services:
  influxdb:
    image: influxdb:2.7
    ports:
      - 8086:8086
    volumes:
      - influxdb_data:/var/lib/influxdb2
    environment:
      DOCKER_INFLUXDB_INIT_MODE: setup
      DOCKER_INFLUXDB_INIT_USERNAME: admin
      DOCKER_INFLUXDB_INIT_PASSWORD: password
      DOCKER_INFLUXDB_INIT_ORG: organization
      DOCKER_INFLUXDB_INIT_BUCKET: bucket-name
      DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: super-secret-token

volumes:
  influxdb_data:

Start the container by running this command

docker compose -f influxdb-compose.yml up -d

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment