| skill | load-test-runner |
| version | 1.0.0 |
| trigger | user asks to run a load test, benchmark an API, generate HTTP traffic, or check performance thresholds |
load-test-runner Skill
When to Use
Use this skill when the user wants to:
- Run an HTTP load test against an API or service
- Check whether a service meets latency or throughput SLAs
- Generate HTTP traffic with configurable concurrency and duration
- View or compare results from previous test runs
- Integrate load testing into a CI/CD pipeline
Prerequisites
- Node.js 20+
- pnpm 9+
- load-test-runner server running (
pnpm --filter server dev or Docker)
- A YAML scenario file or an existing saved scenario
CLI Quick Reference
# Run a scenario file
load-test run ./api-smoke.yaml
# Run and output JSON for CI
load-test run ./api-smoke.yaml --json
# Run without streaming output (quiet mode)
load-test run ./api-smoke.yaml --no-stream
# List recent runs
load-test runs
# List runs for a specific scenario
load-test runs --scenario "API Smoke Test" --limit 10
# View results for a specific run
load-test results run_a1b2c3
# Validate a scenario file without running it
load-test validate ./api-smoke.yaml
# List saved scenarios
load-test scenarios
# Point CLI at a remote server
load-test run ./api-smoke.yaml --api-url https://loadtest.internal.example.com
Environment Variables
| Variable | Required | Default | Description |
|---|
PORT | no | 3000 | HTTP server port |
DATABASE_PATH | no | ./data/ltr.db | SQLite database file path |
API_KEY | no | (none) | API key required for all requests when set |
WORKER_THREADS | no | CPU count | Number of worker threads for load generation |
MAX_VUS | no | 1000 | Global cap on virtual users per run |
LOG_LEVEL | no | info | Log level: debug, info, warn, error |
Boolean env vars use 1 to enable, 0 to disable:
| Variable | Default | Description |
|---|
VERIFY_SSL | 1 | Verify TLS certificates on target requests |
STOP_ON_THRESHOLD_BREACH | 0 | Abort run when any threshold is violated |
AUTO_OPEN_RESULTS | 0 | Print results URL after run completes |
Scenario YAML Format
name: API Smoke Test
description: Basic load test for the REST API
target: https://api.example.com
ramp_up_seconds: 30
duration_seconds: 120
max_vus: 50
steps:
- name: Get health
method: GET
path: /health
expected_status: 200
weight: 10
- name: List items
method: GET
path: /items
headers:
Authorization: Bearer ${TOKEN}
expected_status: 200
weight: 40
- name: Create item
method: POST
path: /items
body:
Field reference:
| Field | Type | Required | Description |
|---|
name | string | yes | Scenario display name |
target | string | yes | Base URL for all requests |
ramp_up_seconds | integer | yes | Seconds to ramp from 0 to max_vus |
duration_seconds | integer | yes | Total test duration including ramp |
max_vus | integer | yes | Maximum virtual users |
steps | array | yes | Request steps (at least one) |
steps[].name | string | yes | Step display name |
steps[].method | string | yes | HTTP method: GET, POST, PUT, PATCH, DELETE |
steps[].path | string | yes | Path appended to target |
steps[].weight | integer | no | Relative frequency weight (default: 1) |
steps[].expected_status | integer | no | Expected HTTP status; non-match = error |
steps[].headers | object | no | HTTP headers as key/value pairs |
steps[].body | string | no | Request body string |
thresholds.p95_response_ms | number | no | Fail if p95 latency exceeds this value in ms |
thresholds.error_rate | number | no | Fail if error rate exceeds this fraction (0.01 = 1%) |
thresholds.rps_min | number | no | Fail if avg RPS falls below this value |
API Routes
All routes accept Authorization: Bearer <api-key> when API_KEY is set.
| Method | Path | Description |
|---|
GET | /api/scenarios | List all scenarios |
POST | /api/scenarios | Create scenario from YAML body |
GET | /api/scenarios/:id | Get scenario detail |
PUT | /api/scenarios/:id | Update scenario YAML |
DELETE | /api/scenarios/:id | Delete scenario |
POST | /api/scenarios/:id/run | Start a run |
POST | /api/runs | Start a run from inline YAML body |
GET | /api/runs | List runs (query: scenarioId, limit, offset) |
GET | /api/runs/:id | Get run summary |
GET | /api/runs/:id/stream | SSE stream for live run updates |
DELETE | /api/runs/:id | Abort an active run |
GET | /api/runs/:id/stats | Get per-second stats for a run |
CI/CD Integration
#!/bin/bash
set -e
RESULT=$(load-test run ./api-smoke.yaml --json)
ALL_PASS=$(echo "$RESULT" | jq -r '.all_pass')
if [ "$ALL_PASS" != "true" ]; then
echo "Load test failed - threshold violations detected"
echo "$RESULT" | jq '.thresholds'
exit 1
fi
echo "Load test passed"
Exit codes:
0 - run completed, all thresholds pass (or no thresholds defined)
1 - run completed, one or more thresholds failed
2 - run aborted, scenario validation error, or fatal error
Troubleshooting
"Cannot connect to server"
Check that the server is running: curl http://localhost:3000/api/scenarios
"Scenario validation failed"
Run load-test validate ./scenario.yaml for detailed errors. Common issues: missing target, duration_seconds less than ramp_up_seconds, no steps defined.
"Max VUs exceeded"
The max_vus field in your scenario exceeds the server-side MAX_VUS limit. Lower max_vus or raise the server limit.
"High error rate on HTTPS targets"
If the target uses a self-signed cert, set VERIFY_SSL=0 in the server environment or pass --insecure in the scenario step headers (not available; set env var).
High CPU during runs
Each virtual user is implemented as a lightweight async loop in a worker thread. The default thread count equals CPU cores. For very high VU counts, increase WORKER_THREADS.