Files

1.6 KiB

k6 Load Testing

Reproducible load test profile for POST /api/v1/decide.

Prerequisites

  • Docker + Docker Compose
  • jq
  • Running stack (docker compose -f compose.yaml up -d)

One-command run

./infrastructure/k6/run-decide.sh

This command:

  1. Prepares deterministic fixture via prepare_k6_fixture.
  2. Runs grafana/k6 in a pinned container image.
  3. Saves artifacts to artifacts/k6/<RUN_ID>/.

Artifacts:

  • fixture.json
  • run.env
  • summary.json

Reproducible rerun

Use the same RUN_ID and k6 profile parameters.

RUN_ID=baseline_20260224 \
START_RPS=20 \
RAMP_UP_RPS=200 \
HOLD_RPS=200 \
HOLD_DURATION=2m \
./infrastructure/k6/run-decide.sh

Target URL

Default target for k6 container:

  • K6_BASE_URL=http://host.docker.internal

Override if needed:

K6_BASE_URL=http://host.docker.internal:14609 ./infrastructure/k6/run-decide.sh

Profile knobs

  • START_RPS
  • RAMP_UP_RPS
  • HOLD_RPS
  • RAMP_UP_DURATION
  • HOLD_DURATION
  • RAMP_DOWN_DURATION
  • PRE_ALLOCATED_VUS
  • MAX_VUS
  • THRESHOLD_ERROR_RATE
  • THRESHOLD_P95_MS
  • THRESHOLD_P99_MS
  • K6_IMAGE

Compare two runs

BASE=artifacts/k6/baseline_20260224/summary.json
CAND=artifacts/k6/candidate_20260224/summary.json

jq -n --argfile b "$BASE" --argfile c "$CAND" '{
  baseline_p95_ms: $b.metrics.http_req_duration["p(95)"],
  candidate_p95_ms: $c.metrics.http_req_duration["p(95)"],
  baseline_req_per_s: $b.metrics.http_reqs.rate,
  candidate_req_per_s: $c.metrics.http_reqs.rate,
  baseline_error_rate: $b.metrics.http_req_failed.value,
  candidate_error_rate: $c.metrics.http_req_failed.value
}'