GimmeJob
Sign in
Performance testing · Chapter 06 / 09

Performance Testing

k6 and Locust

The important skill is not memorizing three tools. It is recognizing how each tool expresses the same performance concepts: workload, user behavior, timing, metrics, pass/fail objectives and scaling of the generator.

k6: code-first scenarios

k6 scripts are JavaScript, while workload scheduling is configured in options. A compact closed-model example is:

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

export const options = {
  scenarios: {
    checkout_load: {
      executor: 'ramping-vus',
      stages: [
        { duration: '1m', target: 20 },
        { duration: '5m', target: 20 },
        { duration: '1m', target: 0 },
      ],
    },
  },
  thresholds: {
    http_req_failed: ['rate<0.01'],
    http_req_duration: ['p(95)<500'],
  },
};

export default function () {
  const response = http.get('https://test.example/api/products');
  check(response, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}

The threshold values are syntax examples. Real limits must come from the product's objectives.

k6 executors and workload meaning

The executor is part of the test model:

  • constant-vus, ramping-vus — load expressed through a VU population;
  • constant-arrival-rate, ramping-arrival-rate — load expressed through iteration arrivals.

Arrival-rate executors implement an open model. Use them when real arrivals continue independently of how slowly current users are being served.

Example:

export const options = {
  scenarios: {
    api_arrivals: {
      executor: 'constant-arrival-rate',
      rate: 50,
      timeUnit: '1s',
      duration: '5m',
      preAllocatedVUs: 100,
    },
  },
};

That expresses an intent to start 50 iterations per second. Always confirm the generator actually maintains the intended rate and watch dropped/insufficient-capacity signals.

k6 thresholds

Thresholds are one of k6's strongest CI concepts. They turn metrics into a process exit status. Typical dimensions are percentile latency, errors and business checks. Keep the gate tied to a specific workload and stable environment; a threshold without those conditions is not reproducible.

Locust: user behavior in Python

Locust models behavior as Python user classes and tasks.

from locust import HttpUser, between, task


class ApiUser(HttpUser):
    wait_time = between(1, 3)

    @task(3)
    def list_products(self):
        with self.client.get('/api/products', catch_response=True) as response:
            if response.status_code != 200:
                response.failure(f'unexpected status {response.status_code}')

    @task(1)
    def health(self):
        self.client.get('/api/health')

Task weights model relative behavior; wait_time controls the delay between tasks. This is a workload description, not a guarantee of a specific RPS.

Headless Locust

locust -f locustfile.py --headless -H https://test.example -u 200 -r 20 -t 15m

According to Locust configuration semantics:

  • -u 200 — peak concurrent users;
  • -r 20 — spawn 20 users per second;
  • -t 15m — run-time limit.

The spawn rate tells you how quickly the user population is reached, not the request throughput.

Distributed Locust

When one process or machine cannot generate the needed load, Locust supports master/worker execution. The master coordinates the run and aggregates statistics; workers run users. Recent Locust documentation recommends multiple worker processes when CPU becomes the generator constraint.

Example topology:

# master
locust -f locustfile.py --master

# worker
locust -f locustfile.py --worker --master-host 10.0.0.10

Monitor worker CPU and achieved RPS. A load generator that cannot reach the requested load invalidates the conclusion about target capacity.

Tool-selection principle

Choose by protocol support, workload model, scripting/correlation needs, expected scale, CI/reporting integration, team skills and operational constraints. Use a small proof of concept and measure generator headroom. Tool popularity is not a test requirement.

Source registry

Chapter references verified
Grafana k6 documentation — Scenarios

VU-based and arrival-rate executors, scenario isolation and workload scheduling

Grafana Labs · Official documentation
Source ↗
Grafana k6 documentation — Open and closed models

Closed versus open workload models and coordinated-omission implications

Grafana Labs · Official documentation
Source ↗
Grafana k6 documentation — Thresholds

Metric pass/fail criteria, percentiles, error-rate limits, SLO encoding and automation

Grafana Labs · Official documentation
Source ↗
Locust documentation — Configuration

Concurrent users, spawn rate, run time and headless execution

Locust · Official documentation
Source ↗
Locust documentation — API

HttpUser, task weighting, wait time and user behavior modelling

Locust · Official documentation
Source ↗
Locust documentation — Distributed load generation

Master/worker execution, multiprocess scaling and load-generator CPU constraints

Locust · Official documentation
Source ↗