Tags: performance-testing, k6, jmeter, load-testing, stress-testing, latency, throughput
Level: intermediate
TL;DR: Performance testing evaluates latency, throughput, and stability under workload. Focus on defining precise SLAs, choosing the right test profile, and identifying bottlenecks before production release.
Load testing verifies system behavior under expected normal and peak traffic conditions.
Stress testing evaluates stability and recovery by pushing traffic beyond breaking points.
Soak or endurance testing identifies memory leaks and resource exhaustion over prolonged periods.
Spike testing measures system resilience during sudden, dramatic traffic surges.
Latency tracks elapsed duration per request, commonly evaluated at p95 and p99 percentiles.
Throughput measures completed transactions or requests handled per unit of time (RPS/TPS).
Saturation tracks hardware and resource utilization limits across CPU, memory, disk, and network.
Baseline metrics establish historical performance reference points across continuous deployment cycles.
Bottlenecks typically originate in database locking, thread pool exhaustion, or downstream service latency.
Q: How do you determine whether a system passed a performance test?R: I compare collected metrics against predefined SLAs or SLOs, verifying that p95/p99 latency stays within thresholds, error rates remain under 1%, and throughput meets target RPS without host resource saturation.
Q: What is the difference between average response time and percentile latency?R: Average response time masks severe tail latency anomalies. I evaluate p95 or p99 percentiles to measure the real degraded experience felt by the slowest requests.
Q: Where do you start troubleshooting when a service degrades under high load?R: I inspect saturation metrics across CPU, memory, and I/O alongside application metrics like database connection pool limits, GC pause times, and slow queries.
Testing against non-representative data volumes or empty development databases.
Ignoring network latency and load balancer routing differences between staging and production.
Relying exclusively on average response times while missing severe p99 spikes.
Generating load from a single machine that bottlenecks on client-side CPU or network sockets.
Running performance runs without warmup periods, skewing metrics with cold-start overhead.
Overlooking downstream mock latencies, leading to unrealistic upstream throughput figures.
// k6 load test script with threshold gates
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 },
{ duration: '1m', target: 50 },
{ duration: '20s', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<400', 'p(99)<800'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const res = http.get('https://api.example.com/v1/health');
check(res, { 'status is 200': (r) => r.status === 200 });
sleep(1);
}
Bash
# Execute k6 test run headlessly with summary export
k6 run --summary-export=summary.json script.js
[ ] Little's Law formula (L=λ×WL = \lambda \times WL=λ×W) and queueing theory basics
[ ] Connection pool exhaustion indicators in relational databases
[ ] Interpreting garbage collection stop-the-world pauses in APM dashboards
[ ] Tail latency mitigation patterns like hedging and circuit breakers
[x] Differences between load, stress, spike, and soak test profiles