Your app works. Every button clicks, every form submits, and the demo dazzled the board. Then marketing fires off a campaign, twelve thousand people hit the checkout page inside ten minutes, and the whole thing folds — timeouts, 502s, a database pinned at 100% CPU. The code was never wrong. It was simply never asked how much weight it could carry.
That gap — between "it works" and "it works under load" — is exactly where performance testing lives. And the goal isn't to prove your system is fast. It's to find the point where it stops coping, on your terms, in a lab, before a real crowd finds it for you.
What performance testing actually measures
"Performance testing" is an umbrella, and treating it as one activity is the first mistake. Underneath it sit distinct questions:
- Load testing — does the system hold its response times at the traffic you expect on a normal busy day?
- Stress testing — where is the breaking point, and what happens when you cross it? Does it degrade gracefully or fall over?
- Spike testing — what happens when traffic jumps 10x in thirty seconds, the way it does after a TV mention or a push notification?
- Soak (endurance) testing — run it at moderate load for eight hours. Memory leaks, connection-pool exhaustion, and a log disk filling up only surface over time.
- Scalability testing — when you double the servers, do you get double the throughput, or does a shared database cap you at 1.3x?
Each answers a different business risk. Pick the ones that map to how your users actually arrive.
The breaking point is data, not a disaster
Engineers treat the moment the system falls over as something to avoid. I treat it as the single most valuable number in the exercise. If you don't know your breaking point, you're guessing at capacity — and you'll either over-provision and burn money, or under-provision and burn trust.
To find it, you watch three numbers as you ramp traffic up:
- Throughput — requests per second the system successfully handles.
- Latency, at percentiles — not the average. The average is a comforting lie. If your mean response is 200ms but your p99 is 6 seconds, one in a hundred users is having a miserable time — and at scale that's thousands of people.
- Error rate — the moment errors start climbing, you've found the knee of the curve.
The breaking point isn't the crash. It's the load level just before response times spike and errors begin — that's your real capacity ceiling.
Running one without fooling yourself
Most performance tests are wrong in the same predictable ways. A useful one looks like this:
- Model real traffic. Pull your actual request mix from production logs. A test that hammers one cheap endpoint tells you nothing; real users log in, search, add to cart, and pay in messy proportions.
- Set targets before you start. Decide the SLO up front — say, "p95 under 500ms at 2,000 concurrent users, error rate below 0.1%." Without a number to pass or fail against, you're just generating graphs.
- Test something production-shaped. Load testing on a laptop, or against a single under-powered staging box, measures the laptop. Same instance types, same data volume, same network path.
- Ramp, don't slam. Increase load in stages and hold at each level. You want to watch the curve bend, not just learn whether it survived one blast.
- Watch the system, not the load generator. The client tells you responses got slow. The server — CPU, memory, DB connections, queue depth — tells you why. That "why" is the entire point.
Tooling is the easy part. k6 and Locust are pleasant for engineers who want tests as code; Gatling and JMeter remain reliable workhorses. The tool matters far less than the workload model you feed it.
Where to start
If you've never load-tested the thing you run in production, don't design a grand testing platform. Pick your single most important user journey — usually checkout, login, or search — write a script that drives it at realistic proportions, and ramp until something breaks. That first breaking number will tell you more about your real capacity than a quarter of dashboard-watching.
Then put it in your pipeline, so the next regression fails a test instead of a customer. The breaking point is going to be found either way. The only question is whether you find it first.