Functional tests answer "does it work". Load tests answer the questions that surface later and hurt more: how many users will the service survive, where does it break, and what happens at a spike. Answering them in production is expensive; that is what load testing is for.
Kinds of load: four questions — four tests
- Load test — "can we hold the expected traffic?": apply the planned load (say, 200 requests per second) and check whether latency stays within target.
- Stress test — "where is the limit and how do we fail?": ramp the load until degradation. What matters is not only the ceiling but the character of the failure: graceful slowdown or an avalanche of errors and a crash.
- Soak test — "will we survive the night?": moderate load for hours. It catches what ten minutes never show: memory leaks, connection exhaustion, swelling caches.
- Spike test — "will we survive a burst?": a sharp jump (an ad aired, a campaign email went out) and a return to normal. It tests autoscaling and queues.
Metrics: what to measure
Throughput — requests per second (RPS/TPS). Errors — the share of non-2xx and timeouts. And above all — latency in percentiles:
- p50 (median) — the typical user;
- p95/p99 — the tail: every twentieth/hundredth request is slower than this.
The arithmetic mean is the worst latency metric: an average of 80 ms can hide a p99 of 4 seconds, and the suffering 1% on a large service is thousands of people. SLAs are stated in percentiles: "p99 < 300 ms at 500 RPS, errors < 0.1%".
Watch the pair together: as load grows, RPS climbs linearly, then flattens — and latency near the plateau shoots up. That is the system's limit (saturation).
Tools
| JMeter | Gatling | k6 | |
|---|---|---|---|
| Scenarios | GUI + XML | code, Scala/Java DSL | code, JavaScript |
| Strength | maturity, plugins, any protocol | efficiency, built-in reports | simplicity, CI-friendliness, single binary |
| Weakness | heavy XML scenarios, costly threads | DSL learning curve | fewer non-HTTP protocols |
| Fits | teams invested in it, exotic protocols | JVM teams, scenarios as code | new projects, load in the pipeline |
Practical rule: for a new HTTP/gRPC project start with k6 or Gatling — scenarios live in git and run in CI. JMeter is chosen for exotic protocols and accumulated expertise.
Method: five steps
- A goal from the SLA: "p99 < 300 ms at 500 RPS" — without a goal the test cannot be interpreted.
- A realistic scenario: the production mix of operations (95% reads / 5% writes, not a uniform GET), realistic data, cache warm-up as a separate stage.
- A production-like stand: the same CPU/memory limits, the same database with production-sized data. A test against an empty database on an oversized stand measures nothing.
- The generator must not be the bottleneck: drive load from a separate machine (not a laptop over VPN) and verify it is the system that saturates, not the generator.
- Analysis at the plateau: application and infrastructure metrics (monitoring during the test) — CPU, DB connection pool, GC pauses: the limit always hits something specific.
Typical mistakes
- Looking at the mean instead of percentiles — see above.
- Measuring without warm-up: for the first minutes a JVM service is warming JIT and caches; those numbers say nothing about production.
- Ignoring coordinated omission: if the generator waits for a response before sending the next request, it slows down together with the service and understates tail latency. Tools with an open workload model (k6 arrival rate, Gatling) protect against this.
- A single run: a result without repetition is chance, not measurement.
In short
- Four kinds: load — planned traffic, stress — finding the limit, soak — hours of work (leaks), spike — a sharp burst.
- Metrics: RPS, error share, and latency percentiles (p50/p95/p99); the mean misleads, SLAs are written in percentiles.
- Tools: k6 — JS scenarios and CI; Gatling — code and reports for JVM teams; JMeter — maturity and non-HTTP protocols.
- Method: goal from SLA → realistic scenario → production-like stand → generator not the bottleneck → analysis at saturation.
- The big traps: means instead of percentiles, no warm-up, coordinated omission, conclusions from one run.
What to read next
- The test pyramid — where load tests live among the rest.
- Observability — load-test analysis is blind without application metrics.
- Load balancing — what stands between the user and your limit.