performance load-testing ci-cd
Load Testing Best Practices: From Script to Production
Published on March 5, 2026 · by PerfBlog Team
The Art of Load Testing
Load testing isn’t just about throwing traffic at your application. It’s about simulating reality to uncover performance issues before your users do.
Designing Effective Test Scenarios
Think Like Your Users
A good load test mirrors real user behavior:
// k6 example: realistic user scenario
import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
stages: [
{ duration: '2m', target: 50 }, // ramp up
{ duration: '5m', target: 50 }, // steady state
{ duration: '2m', target: 100 }, // peak load
{ duration: '5m', target: 100 }, // sustained peak
{ duration: '2m', target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
// Browse homepage
let res = http.get('https://app.example.com/');
check(res, { 'homepage status 200': (r) => r.status === 200 });
sleep(Math.random() * 3 + 1); // think time
// Search for product
res = http.get('https://app.example.com/api/search?q=laptop');
check(res, { 'search status 200': (r) => r.status === 200 });
sleep(Math.random() * 2 + 1);
// View product details
res = http.get('https://app.example.com/api/products/123');
check(res, { 'product status 200': (r) => r.status === 200 });
sleep(Math.random() * 5 + 2);
}
The Ramp-Up Pattern
Never hit your system with full load instantly. Always use a gradual ramp-up:
- Warm-up phase (2-5 min): Let caches fill, connections establish
- Ramp-up (2-5 min): Gradually increase to target load
- Steady state (5-15 min): Maintain constant load
- Peak (5-10 min): Push to expected peak
- Ramp-down (2-5 min): Gradually decrease
Analyzing Results
Key Indicators of Problems
- Response time increasing linearly with load = resource bottleneck
- Sudden error spike at specific load = capacity limit reached
- Increasing response time over time at constant load = memory leak
- High variance in response times = inconsistent performance
Response Time Percentiles
Don’t rely on averages. Use percentiles:
| Percentile | What it tells you |
|---|---|
| p50 (median) | Typical user experience |
| p90 | Most users’ worst case |
| p95 | SLA-critical threshold |
| p99 | Tail latency issues |
CI/CD Integration
Integrate performance tests into your pipeline:
# GitHub Actions example
performance-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run k6 load test
uses: grafana/k6-action@v0.3.1
with:
filename: tests/load-test.js
flags: --out json=results.json
- name: Check thresholds
run: |
if grep -q '"thresholds":.*"failed":true' results.json; then
echo "Performance thresholds exceeded!"
exit 1
fi
Common Mistakes to Avoid
- Testing from the same machine - Use distributed load generation
- Ignoring think times - Real users pause between actions
- Not monitoring server-side - CPU, memory, DB connections matter
- Testing only happy paths - Include error scenarios
- Running once - Always run multiple iterations for reliable data
Conclusion
Load testing is a skill that improves with practice. Start with simple scenarios, gradually add complexity, and always tie results back to business requirements.