Build an AI Load Test Scenario Generator with Claude API
Writing realistic k6 or Locust load test scenarios means understanding actual traffic patterns, not just hammering one endpoint. Build a tool that reads your API spec and real traffic logs, then generates realistic load test scripts with Claude API.
Most hand-written load tests hit one endpoint at a fixed rate — which tells you almost nothing about how the system behaves under realistic, mixed traffic with actual user session patterns. This tool reads your OpenAPI spec and sampled access logs to generate a load test that resembles real usage, not a synthetic stress test that misses the failure modes that actually matter.
Setup
pip install anthropic pyyaml
# k6 CLI installed separately: https://k6.io/docs/get-started/installation/Traffic Pattern Analyzer
import anthropic
import json
from collections import Counter
client = anthropic.Anthropic()
def analyze_access_logs(log_sample: list[dict]) -> dict:
"""Extract realistic traffic patterns from sampled production access logs."""
endpoints = Counter(f"{log['method']} {log['path']}" for log in log_sample)
total = sum(endpoints.values())
return {
"endpoint_distribution": {ep: round(count / total * 100, 1) for ep, count in endpoints.most_common(20)},
"avg_requests_per_session": estimate_session_length(log_sample),
"peak_to_average_ratio": calculate_peak_ratio(log_sample),
}
def estimate_session_length(log_sample: list[dict]) -> float:
sessions = Counter(log.get("session_id") for log in log_sample if log.get("session_id"))
return sum(sessions.values()) / len(sessions) if sessions else 1.0Scenario Generation With Claude
GENERATE_PROMPT = """Generate a realistic k6 load test script based on this
production traffic pattern data.
OpenAPI spec (relevant endpoints):
{openapi_spec}
Real traffic distribution (% of requests per endpoint):
{endpoint_distribution}
Average requests per user session: {avg_session_length}
Peak-to-average traffic ratio: {peak_ratio}
Requirements:
- Model realistic user sessions (login -> browse -> action -> logout pattern),
not independent random requests to each endpoint
- Weight virtual user behavior to match the real endpoint distribution
- Include a ramp-up stage, sustained peak stage (using the peak ratio), and ramp-down
- Add realistic think-time between requests (1-3s), not zero-delay hammering
- Include response time and error rate thresholds as pass/fail criteria
Generate a complete, runnable k6 script."""
def generate_load_test(openapi_spec: dict, traffic_patterns: dict) -> str:
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=3000,
messages=[{
"role": "user",
"content": GENERATE_PROMPT.format(
openapi_spec=json.dumps(openapi_spec, indent=2)[:3000],
endpoint_distribution=traffic_patterns["endpoint_distribution"],
avg_session_length=traffic_patterns["avg_requests_per_session"],
peak_ratio=traffic_patterns["peak_to_average_ratio"],
)
}]
)
text = response.content[0].text
if "```javascript" in text or "```js" in text:
text = text.split("```")[1]
text = text.replace("javascript", "", 1).replace("js", "", 1).strip()
return textExample Generated Output
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 50 }, // ramp-up
{ duration: '10m', target: 200 }, // sustained peak (4x average, from real ratio)
{ duration: '2m', target: 0 }, // ramp-down
],
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
// Weighted to match real traffic: 45% browse, 30% search, 15% checkout, 10% account
const rand = Math.random();
http.get('https://api.myapp.com/health'); // session start
sleep(1);
if (rand < 0.45) {
http.get('https://api.myapp.com/products?page=1');
sleep(2);
http.get(`https://api.myapp.com/products/${randomProductId()}`);
} else if (rand < 0.75) {
http.get(`https://api.myapp.com/search?q=${randomSearchTerm()}`);
} else if (rand < 0.90) {
const cartRes = http.post('https://api.myapp.com/cart', JSON.stringify({ item_id: randomProductId() }));
check(cartRes, { 'add to cart succeeds': (r) => r.status === 200 });
sleep(1);
http.post('https://api.myapp.com/checkout');
} else {
http.get('https://api.myapp.com/account');
}
sleep(Math.random() * 2 + 1); // realistic think-time
}Wiring Into CI for Regular Load Testing
# .github/workflows/load-test.yml
name: Weekly Load Test
on:
schedule:
- cron: "0 3 * * 0" # Weekly, low-traffic window
workflow_dispatch:
jobs:
load-test:
runs-on: ubuntu-latest
steps:
- uses: grafana/k6-action@v0.3.1
with:
filename: generated-load-test.js
- name: Fail if thresholds not met
run: echo "k6 exits non-zero automatically on threshold failure"Why Traffic-Shape Accuracy Matters
A load test that hammers one endpoint at constant RPS will pass cleanly on a system whose real bottleneck is a slow database query that only surfaces when checkout, search, and browse traffic overlap during a realistic peak. Generating scenarios from actual endpoint distribution and session patterns is what makes load testing catch the failure modes that matter in production, instead of confirming a synthetic scenario nobody will ever actually hit.
More AI DevOps tooling? Read our Build AI synthetic test generator with Claude API and Build AI deployment health checker with Claude API.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Build an AI ChatOps Incident Bot for Slack with Claude API
Build a Slack bot that turns '/incident api is down' into a full incident channel with a Claude-generated initial assessment, relevant runbook links, and the right people paged automatically.
Build an AI Incident Timeline Reconstructor with Claude API
Writing an incident timeline after the fact means manually cross-referencing Slack messages, deploy logs, alert timestamps, and PagerDuty events. Build a tool that pulls all of it together and generates an accurate, chronological timeline with Claude API.
Build an AI Runbook Generator with Claude API and Git History
Auto-generate incident runbooks from your git history, monitoring alerts, and past incidents using Claude API. Runbooks stay up to date automatically as your code changes — no manual maintenance.