Articles

What Is Load Testing?

Load testing measures how a system behaves under expected and peak traffic, revealing bottlenecks and capacity limits before real users do.

The Lycoris Team The Lycoris Team · · 4 min read
Rows of server racks in a data center

Load testing is the practice of simulating realistic traffic against a system to see how it behaves — how response times change as concurrent requests increase, where throughput plateaus, and what breaks first when demand exceeds capacity. It’s how a team finds out that a service falls over at 500 requests per second before a real product launch does it for them, and answers questions monitoring alone can’t: not “is this slow right now,” but “how much headroom do we actually have.”

What load testing measures

A load test drives synthetic traffic against a system — usually a staging environment that mirrors production, sometimes production itself during a controlled window — and records how key metrics respond as load increases:

  • Latency — how response time shifts as concurrency rises, particularly at the tail (p95, p99) rather than just the average.
  • Throughput — the maximum sustained request rate the system handles before latency or error rate degrades.
  • Error rate — at what load level requests start failing outright, timing out, or returning 5xx responses.
  • Resource saturation — CPU, memory, database connections, or queue depth as the bottleneck, which often reveals why a system degrades, not just when.

The goal isn’t a single pass/fail number. It’s a curve: response time and error rate as a function of load, which tells you both your comfortable operating capacity and how gracefully — or badly — the system degrades past it.

Load testing vs stress testing vs soak testing

These three terms get used loosely, but they answer different questions:

Test typeQuestion it answersTypical duration
Load testingHow does the system perform at expected/peak traffic?Minutes to an hour
Stress testingWhere does the system actually break, beyond expected traffic?Until failure
Soak testingDoes performance degrade over a long sustained run?Hours to days

Stress testing deliberately pushes past realistic traffic to find the breaking point and observe the failure mode — does the system reject new requests cleanly, or does it degrade in a way that takes down healthy requests too? Soak testing runs a sustained, moderate load for an extended period specifically to catch problems that only show up over time: a memory leak that’s invisible in a ten-minute test but crashes the process after six hours, or a connection pool that slowly exhausts itself.

Where bottlenecks typically show up

Load tests rarely fail evenly — they expose whichever component in the request path has the least headroom, and that’s frequently not the application code itself:

  • Database connections. A fixed-size connection pool can queue or reject requests long before the application server itself is under real strain.
  • Downstream dependencies. A third-party API or internal service with its own rate limits can become the ceiling on your system’s throughput, regardless of how well your own code scales.
  • N+1 queries. Code that looks fine at low traffic because each request is fast can fall over at load simply because it multiplies database round trips — see the N+1 query problem for how this hides until concurrency exposes it.
  • Thread or worker pool exhaustion. A fixed number of worker threads or processes creates a hard ceiling on concurrent request handling, independent of CPU or memory headroom.

A load test’s real value is often not the top-line “requests per second” number but the process of tracing a degradation back to whichever of these was the actual limiting factor — the same instinct behind reading Server-Timing data to see where time actually goes inside a slow request.

Designing a realistic test

A load test is only as useful as its traffic model is realistic. Hammering a single endpoint with identical requests at maximum concurrency tests something, but rarely the thing that matters — real traffic has a mix of endpoints, realistic think-time between a user’s requests, and a distribution of payload sizes and query patterns. Tools in this space (open-source and commercial alike) generally let you script a request mix that approximates real user journeys rather than a single hot path, and ramp load gradually rather than jumping straight to peak concurrency, so you can see where the curve bends rather than only where it breaks.

It’s also worth testing against realistic data volumes. A query that’s instant against a staging database with a thousand rows can behave completely differently against a production-sized table with proper indexing pressure and cache-miss patterns that a small dataset simply can’t reproduce.

Load testing and capacity planning

Load test results feed directly into decisions about horizontal vs vertical scaling — knowing exactly how much headroom each instance has, and how that headroom changes with instance count, is what makes autoscaling thresholds meaningful rather than guesswork. It also informs where a circuit breaker or rate limiter should trip: those defenses are only correctly tuned once you know the load level at which the protected system actually starts to degrade.

Running load tests before a known traffic event — a product launch, a marketing push, a seasonal spike — is one of the more direct ways engineering time converts into avoided downtime, because it turns “we think this can handle the launch” into a measured answer.

The takeaway

Load testing simulates realistic traffic to answer a concrete question: how does this system behave as demand increases, and where does it start to break? Its value comes from the curve it produces — latency and error rate as a function of load — not a single number, and from tracing degradation back to its actual bottleneck, whether that’s a database connection pool, a downstream dependency, or thread exhaustion. Run it against realistic data and realistic traffic patterns, and use the results to set autoscaling thresholds and circuit breaker limits before real traffic finds the ceiling for you.

Chisato Chisato · · 4 min read

Kubernetes Init Containers Explained

Init containers run to completion before a pod's main containers start, making them the standard way to handle setup steps and startup ordering.

#Kubernetes #DevOps #Cloud
Chisato Chisato · · 4 min read

Postgres Logical Replication Explained

Logical replication streams row-level changes between Postgres databases instead of copying raw disk blocks — enabling selective sync, upgrades, and CDC.

#Databases #Cloud #DevOps