| name | perf-test |
| description | Run performance and load tests against an API or web app. Invoke when the user wants to measure response times, throughput, error rates under load, or find performance regressions. Trigger when the user says "load test", "stress test", "performance test", "benchmark my API", "test under load", "how many requests per second can it handle", or provides a URL and wants performance metrics. Also trigger when the user mentions k6, load testing, or wants to check SLAs (response time < 200ms, error rate < 1%).
|
| user-invocable | true |
| allowed-tools | Bash, Read, Write |
| argument-hint | --url <target-url> [--vus 10] [--duration 30s] [--spec <openapi-path>] [--scenario <smoke|load|stress|soak>] |
Performance Testing Skill
You are an expert performance engineer. Use k6 to generate load, collect metrics, and produce an actionable performance report.
Workspace
All output goes into .opentest-workspace/perf/ in the current working directory. Create it before starting:
mkdir -p .opentest-workspace/perf
Add to .gitignore if not already there:
.opentest-workspace/
| Output | Path |
|---|
| Generated k6 script | .opentest-workspace/perf/k6_script.js |
| Raw k6 results | .opentest-workspace/perf/results.json |
| Analysis report | .opentest-workspace/perf/report-<YYYY-MM-DD>.md |
Prerequisites Check
Verify k6 is installed:
uv run .claude/skills/perf-test/scripts/run_perf.py --help
If k6 is not installed, report:
k6 is not installed. Install with:
macOS: brew install k6
Ubuntu: sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update && sudo apt-get install k6
Docker: docker run --rm -i grafana/k6 run - <script.js
Phase 0: Intake
Ask these questions in a single message if not already provided:
- Target URL — API base URL or specific endpoint
- Auth — Bearer token, API key, or none
- OpenAPI spec (optional) — path to spec file (enables multi-endpoint testing)
- Scenario type — which predefined profile to use (see below), or custom VUs + duration
- SLAs (optional) — response time thresholds, acceptable error rate
Scenarios
| Scenario | VUs | Duration | Purpose |
|---|
smoke | 1 | 30s | Verify test setup, baseline latency |
load | 10 | 2m | Typical production load |
stress | 50 | 5m | Find breaking point |
soak | 5 | 10m | Memory leaks, degradation over time |
spike | 0→100→0 | 1m | Sudden traffic spikes |
Step 1: Generate k6 Script + Run Tests
uv run .claude/skills/perf-test/scripts/run_perf.py \
--url <target_url> \
--scenario <scenario> \
[--vus <number>] \
[--duration <duration>] \
[--spec <openapi_path>] \
[--auth '<auth_json>'] \
[--thresholds '<thresholds_json>'] \
--output .opentest-workspace/perf/results.json \
--script-output .opentest-workspace/perf/k6_script.js
The script will:
- Generate a k6 JavaScript load test from the URL/spec
- Execute k6 with the chosen scenario profile
- Collect metrics (p50, p95, p99, req/s, error rate)
- Write structured JSON results
Show the user the generated k6 script path so they can inspect or reuse it in CI.
Step 2: Analyze & Report
After the run, synthesize the JSON results into a performance report:
Report Structure
Lead with the verdict:
- ✅ PASS — all SLA thresholds met
- ⚠️ DEGRADED — most thresholds met, some marginal
- ❌ FAIL — SLA thresholds violated
Then show:
## Performance Summary
Target: <url>
Scenario: <scenario> | VUs: <vus> | Duration: <duration>
Total requests: <n> | Req/s: <n>
### Response Times
p50: <ms>ms
p95: <ms>ms ← SLA threshold: <threshold>ms [PASS/FAIL]
p99: <ms>ms
max: <ms>ms
### Reliability
Error rate: <pct>% [PASS/FAIL]
Timeouts: <n>
Failed checks: <n>
### Throughput
Peak req/s: <n>
Data received: <mb> MB
Findings
Group performance issues by severity:
- 🔴 Critical — error rate > 5% or p95 > 5s (service unusable)
- 🟠 High — p95 > 2s or error rate 1–5%
- 🟡 Medium — p95 > 500ms, below SLA but not catastrophic
- 🔵 Low — observations, not threshold violations
For each finding include: metric name, measured value, threshold, recommendation.
Top 3 Recommendations
End with concrete, prioritized action items. Examples:
- "p99 latency spikes to 4.2s under 50 VUs — likely a missing database index on POST /orders query"
- "Error rate 2.3% at 50 VUs — connection pool exhausted; increase pool size from 10 to 50"
Save the report to .opentest-workspace/perf/report-<YYYY-MM-DD>.md.
Auth Config
{"type": "bearer", "token": "eyJhbGciOiJIUzI1NiJ9..."}
{"type": "api_key", "header": "X-API-Key", "value": "key123"}
Default SLA Thresholds
If the user has not specified thresholds, use these defaults:
{
"http_req_duration": ["p(95)<2000"],
"http_req_failed": ["rate<0.01"]
}
Inform the user what thresholds were used and offer to re-run with custom values.