// Load testing with k6, Gatling, performance benchmarking, and CI/CD integration. Use when testing performance, capacity, or implementing load tests.
| name | moai-testing-load |
| version | 4.0.0 |
| updated | "2025-11-19T00:00:00.000Z" |
| status | stable |
| category | Testing |
| description | Load testing with k6, Gatling, performance benchmarking, and CI/CD integration. Use when testing performance, capacity, or implementing load tests. |
| allowed-tools | ["Read","Bash","WebFetch","WebSearch"] |
| tags | ["performance-testing","load-testing","k6","gatling","benchmarking","ci-cd"] |
Production-grade load testing with k6 and Gatling for enterprise systems.
Choose Your Tool:
5-Minute k6 Example:
# Install k6
brew install k6 # macOS
# or: apt install k6 # Linux
# Create test
cat > load-test.js << 'EOF'
import http from 'k6/http';
import { check } from 'k6';
export const options = {
vus: 100,
duration: '30s',
thresholds: {
'http_req_duration': ['p(95)<200'],
'errors': ['rate<0.01'],
},
};
export default function () {
const response = http.get('https://httpbin.org/get');
check(response, {
'status is 200': (r) => r.status === 200,
});
}
EOF
# Run test
k6 run load-test.js
Performance Metrics:
| Type | Load | Purpose | Duration | When |
|---|---|---|---|---|
| Smoke | Minimal (10 VU) | Verify basic functionality | 1-2 min | Before deployment |
| Load | Realistic | Measure normal performance | 10-15 min | Weekly/release |
| Stress | Maximum | Find breaking point | 10-15 min | Before traffic spike |
| Spike | Sudden surge | Test surge capacity | 5-10 min | Flash sales prep |
| Soak | Sustained | Find memory leaks | 8+ hours | Before holidays |
# Define your SLOs (Service Level Objectives)
api_gateway:
latency:
p95: 200ms
p99: 500ms
throughput:
target: 5000 RPS
availability:
error_rate: < 0.1%
| Factor | k6 | Gatling |
|---|---|---|
| Language | JavaScript | Scala |
| Learning Curve | Low | Medium |
| Setup | Single binary | JVM required |
| Best For | APIs, microservices | Complex journeys, UI |
| Max VU | 50K/machine | 100K+/machine |
| Open Source | Yes | Yes |
| Cloud Service | k6 Cloud | Gatling Enterprise |
Decision Tree:
Testing APIs/microservices?
→ YES: Use k6
→ NO: Complex user flows?
→ YES: Use Gatling
→ NO: Use k6 (JavaScript is common)
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
stages: [
{ duration: "2m", target: 100 }, // Ramp up
{ duration: "5m", target: 100 }, // Stay at 100
{ duration: "2m", target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ["p(95)<200"],
},
};
export default function () {
const res = http.get("https://api.example.com/users");
check(res, {
"status 200": (r) => r.status === 200,
"response time < 200ms": (r) => r.timings.duration < 200,
});
sleep(1);
}
import { Trend, Rate, Counter } from "k6/metrics";
const apiDuration = new Trend("api_duration_ms");
const errorRate = new Rate("errors");
const requests = new Counter("total_requests");
export default function () {
const res = http.get("https://api.example.com");
apiDuration.add(res.timings.duration);
errorRate.add(res.status !== 200);
requests.add(1);
}
export const options = {
scenarios: {
baseline: {
executor: "ramping-vus",
startVUs: 0,
stages: [
{ duration: "1m", target: 50 },
{ duration: "3m", target: 50 },
{ duration: "1m", target: 0 },
],
},
stress: {
executor: "ramping-vus",
startVUs: 0,
stages: [
{ duration: "2m", target: 200 },
{ duration: "5m", target: 200 },
],
startTime: "5m", // Start after baseline
},
},
};
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._
class BasicSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://api.example.com")
.acceptHeader("application/json")
val scn = scenario("Load Test")
.exec(
http("Get Users")
.get("/users")
.check(status.is(200))
)
.pause(1.second)
setUp(
scn.inject(
rampUsers(100).during(5.minutes)
)
).protocols(httpProtocol)
.assertions(
global.responseTime.percentile3.lt(200),
global.failedRequests.percent.lt(0.1)
)
}
# .github/workflows/load-test.yml
name: Load Tests
on:
schedule:
- cron: "0 2 * * *" # Daily at 2 AM
workflow_dispatch:
jobs:
k6-load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run k6
uses: grafana/k6-action@v0.3.0
with:
filename: tests/load-test.js
flags: --out json=results.json
- name: Check thresholds
run: |
if grep -q '"passed":false' results.json; then
echo "Performance thresholds failed"
exit 1
fi
Common Bottlenecks:
Debugging Process:
1. Run load test with monitoring
2. Identify slow endpoints (>p95)
3. Profile that component (APM tools)
4. Root cause analysis
5. Fix and re-test
6. Track in baseline
APM Tools:
Typical Response Times:
API endpoint (cached):
p50: 50ms
p95: 200ms
p99: 500ms
Database query:
p50: 100ms
p95: 300ms
p99: 1000ms
E-commerce page:
p50: 100ms
p95: 500ms
p99: 2000ms
✅ DO:
❌ DON'T:
For advanced patterns, see:
Related Skills:
moai-essentials-perf: Performance optimizationmoai-observability-advanced: APM and monitoringmoai-testing-integration: Integration testing patterns| Issue | Solution |
|---|---|
| High error rate | Check server capacity, validate test script |
| Inconsistent results | Ensure stable test environment, use ramp-up |
| Slow test execution | Increase VU incrementally, check network |
| Memory issues | Use distributed testing, optimize script |
Version: 4.0.0
Last Updated: 2025-11-19
Status: Production Ready
For detailed examples and API references, see examples.md and reference.md.