// Test application performance, scalability, and resilience. Use when planning load testing, stress testing, or optimizing system performance.
| name | performance-testing |
| description | Test application performance, scalability, and resilience. Use when planning load testing, stress testing, or optimizing system performance. |
| version | 1.0.0 |
| category | testing |
| tags | ["performance","load-testing","stress-testing","scalability","optimization","monitoring"] |
| difficulty | intermediate |
| estimated_time | 45 minutes |
| author | user |
Performance is a feature, not an afterthought.
Test performance like you test functionality: continuously, automatically, and with clear acceptance criteria.
What: System behavior under expected load
Goal: Verify the system handles typical usage
Example:
When: Before every major release
Tools: k6, JMeter, Gatling, Artillery
What: System behavior under extreme load (beyond capacity)
Goal: Find breaking point, see how system fails
Example:
When: Before scaling infrastructure, quarterly at minimum
What to look for: Graceful degradation, not catastrophic failure
What: System behavior under sudden load increase
Goal: Test auto-scaling, handling unexpected traffic
Example:
When: Before major events, after infrastructure changes
Pattern: Instant ramp from normal to 5-10x load
What: System behavior over extended time
Goal: Find memory leaks, resource exhaustion, gradual degradation
Example:
When: After significant code changes, quarterly
What to look for: Stable resource usage over time
What: How system performs as load increases
Goal: Validate horizontal/vertical scaling
Example:
When: Before capacity planning, infrastructure changes
Bad: "The system should be fast" Good: "95th percentile response time < 200ms under 1,000 concurrent users"
Define SLOs (Service Level Objectives):
Don't test everything equally. Focus on:
Bad: Every user hits homepage repeatedly Good:
Include:
Ideal: Production-like infrastructure
Reality: Often scaled-down version
Requirements:
Example:
Products: 100,000 (matching production)
Users: 50,000 test accounts
Orders: 1M historical orders
Search queries: Real query distribution
Essential metrics:
Tools:
Symptoms:
Solutions:
Problem:
// Load 100 orders
const orders = await Order.findAll();
// For each order, load customer (100 queries!)
for (const order of orders) {
const customer = await Customer.findById(order.customerId);
}
Fix:
// Load orders with customers in one query
const orders = await Order.findAll({
include: [Customer]
});
Problem: Blocking operations in request path
Example: Sending email during checkout
Fix:
Symptoms:
Detection:
Common causes:
Problem: Recalculating same results repeatedly
Strategy:
Balance: Cache hit rate vs. memory usage
Problem: Third-party APIs slow or unavailable
Solutions:
Approach 1: Smoke Tests
Approach 2: Nightly Tests
Approach 3: Pre-Production Gate
// performance-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '1m', target: 50 }, // Ramp up
{ duration: '3m', target: 50 }, // Stay at 50 users
{ duration: '1m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<200'], // 95% of requests < 200ms
http_req_failed: ['rate<0.01'], // < 1% failures
},
};
export default function () {
const res = http.get('https://api.example.com/products');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 200ms': (r) => r.timings.duration < 200,
});
sleep(1);
}
# .github/workflows/performance.yml
name: Performance Tests
on:
pull_request:
branches: [main]
jobs:
performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run k6 test
uses: grafana/k6-action@v0.3.0
with:
filename: performance-test.js
- name: Upload results
uses: actions/upload-artifact@v2
with:
name: k6-results
path: results.json
Response Time Distribution:
Throughput:
Error Rate:
Good:
Load: 1,000 users
Response time p95: 180ms
Throughput: 5,000 req/s
Error rate: 0.05%
CPU: 65%, Memory: 70%
Problems:
Load: 1,000 users
Response time p95: 3,500ms โ (too slow)
Throughput: 500 req/s โ (way below target)
Error rate: 5% โ (too many errors)
CPU: 95%, Memory: 90% โ (maxed out)
What: Automated tests hitting production
Example:
Tools: Pingdom, Datadog Synthetics, New Relic Synthetics
What: Measure actual user experience
Metrics:
Tools: Google Analytics, New Relic Browser, Datadog RUM
Set alerts on:
Don't alert on:
Problem: Find performance issues in production
Fix: Test early and often, catch issues before release
Problem: Test doesn't match real usage
Example: All users hitting same endpoint simultaneously
Fix: Model realistic user journeys, think time, data distribution
Problem: 0 to 1,000 users instantly
Real world: Traffic grows gradually (usually)
Fix: Ramp up over time, see how system adapts
Problem: Can't see what's happening during test
Fix: Monitor everything during tests
Problem: Don't know if results are good or bad
Fix: Establish baseline, track trends over time
Problem: Test once before launch, never again
Fix: Continuous performance testing, trend monitoring
k6: Modern, developer-friendly, JavaScript-based
JMeter: Mature, feature-rich, GUI-based
Gatling: Scala-based, great reporting
Artillery: Node.js, simple YAML configs
Locust: Python-based, distributed testing
Problem: Checkout taking 5+ seconds under load
Investigation:
orders.user_idFix:
CREATE INDEX idx_orders_user_id ON orders(user_id);
Result:
Performance is a feature: Test it like functionality Test continuously: Not just before launch Monitor production: Synthetic + real user monitoring Set realistic goals: Based on business requirements Fix what matters: Focus on user-impacting bottlenecks Trend over time: Performance degrades gradually, catch it early
qe-performance-tester orchestrates load testing:
// Agent runs comprehensive load test
const perfTest = await agent.runLoadTest({
target: 'https://api.example.com',
scenarios: {
checkout: { vus: 100, duration: '5m' },
search: { vus: 200, duration: '5m' },
browse: { vus: 500, duration: '5m' }
},
thresholds: {
'http_req_duration': ['p(95)<200'],
'http_req_failed': ['rate<0.01'],
'http_reqs': ['rate>100']
}
});
// Returns detailed performance report
// Agent identifies performance bottlenecks
const analysis = await qe-performance-tester.analyzeBottlenecks({
testResults: perfTest,
metrics: ['cpu', 'memory', 'db_queries', 'network', 'cache_hits']
});
// Returns:
// {
// bottlenecks: [
// { component: 'database', severity: 'high', suggestion: 'Add index on orders.created_at' },
// { component: 'api', severity: 'medium', suggestion: 'Enable response caching' }
// ]
// }
// Agent integrates performance testing in CI/CD
const ciPerformance = await qe-performance-tester.ciIntegration({
mode: 'smoke', // Quick test on every commit
duration: '1m',
vus: 10,
failOn: {
'p95_response_time': 300, // ms
'error_rate': 0.01 // 1%
}
});
const performanceFleet = await FleetManager.coordinate({
strategy: 'performance-testing',
agents: [
'qe-performance-tester', // Run load tests
'qe-quality-analyzer', // Analyze results
'qe-production-intelligence', // Compare to production
'qe-deployment-readiness' // Go/no-go decision
],
topology: 'sequential'
});
Testing:
Quality:
Performance testing isn't optionalโit's how you ensure your system works when it matters most.