Load Testing

Load testing is a type of performance testing that checks how a system behaves under the load it is expected to carry. ISTQB describes it as testing under anticipated loads, from low through typical to peak usage, generated by a controlled number of simulated users or processes. The question is concrete: at the expected load, do response times, error rate and resource use stay within what was agreed?

Example: an online store's busiest hour last year averaged 100 requests per second, and the business expects 20% growth. The load test ramps up to 120 requests per second, holds it for 30 minutes and checks, for instance, that search p95 stays within 300 ms and fewer than 0.5% of requests fail. Going past the expected peak is stress testing, the next lesson.

Why it matters

Many performance defects appear only under concurrent load and realistic data volumes: a connection pool that runs out, a lock a hundred checkouts wait for, a query that is fast on ten rows and slow on a million. Functional tests send one request at a time, usually against small test data, and never meet them. If the first real peak finds them, the cost is lost sales, failed bookings or an outage.

For the tester, a load test turns "the system should be fast" into evidence: a defined load, measured results and a verdict against criteria agreed in advance. It supports the release decision, catches performance regressions and gives developers a reproducible run instead of a vague complaint.

Expected load: the number you test against

Expected load is the traffic the system must carry, described with the workload model from the lesson on concurrent users and workload models: which transactions, in what mix, at what rate. Fix it before writing a script, and record where every number came from.

  • Production data: the busiest hour of recent months, per transaction, from analytics, access logs or monitoring, not the daily total spread over 24 hours.
  • Forecasts: campaigns, seasonal peaks, salary day, registration windows. Multiply the measured peak by the agreed growth factor.
  • Levels: test at least the typical busy hour and the expected peak, both loads the system is designed to carry.
  • No history yet: estimate from the number of users and how often they act, and label the estimate an assumption in the plan.

Try it: Performance Test Data Generator

The load profile: ramp-up, steady state, ramp-down

The load profile describes how the applied load changes over time. Of its three stages, only one is the measurement. For the store: ramp up to 120 requests per second over 10 minutes, hold for 30, ramp down over 5.

  • Ramp-up: load rises gradually, as real traffic does, while caches, connection pools and autoscaling warm up. Starting at full load creates a spike nobody asked about and measures a cold system.
  • Steady state: the target load is held constant. The system is steady when throughput matches the applied load and response times and resource use stay flat; response times that keep climbing at constant load mean work is queueing, which is a finding. Hold it long enough for many samples of every transaction, usually tens of minutes; runs of many hours are soak tests.
  • Ramp-down: load returns to zero, and response times, queues and resource use should return to baseline. A system that stays slow afterwards has not recovered.
The store's load test ramps up to the expected peak of 120 requests per second in 10 minutes, holds it for 30 and ramps down in 5; only the steady state is judged against the pass criteria.
  1. Load test at the expected peakOnline store, release 4.2, production mix of search, product page and checkout

    Reference line:expected peak: 120 requests per second (100 last year × 1.2 growth)

    1. 1ramp-up 0–10 min0 → 120 req/s; warm-up, not judged
    2. 2steady state 10–40 min120 req/s held; judged against the pass criteria
    3. 3ramp-down 40–45 min120 → 0 req/s; check recovery to baseline

Ramps are drawn as straight lines; a tool may raise the load in small steps instead.

Try it: Concurrent Request Test Generator

Pass criteria: agreed before the run

Pass criteria give a load test its expected result. They come from non-functional requirements, service level objectives or acceptance criteria, cover the performance efficiency characteristic of ISO/IEC 25010 (time behaviour, resource utilisation, capacity) and are agreed with the product owner and developers before the first run, not after seeing the numbers.

  • Response time per transaction, as percentiles: search p95 ≤ 300 ms, checkout p95 ≤ 800 ms.
  • Error rate: HTTP 5xx and unexpected 4xx responses, timeouts, connection errors and failed content checks below, say, 0.5%.
  • Throughput achieved: at least 95% of the planned 120 requests per second. A run that never reached the target proves nothing about it.
  • Resource ceilings that keep headroom, such as database CPU below 75%.
  • Validity of the test itself: the load generator was not overloaded (CPU below 80%) and responses were checked for content, not only for status 200.
  • Window: judge the steady state only. Load tools often compute their built-in thresholds over every sample, ramps included, so filter the steady-state window first.

Planning and running a load test

Write a short plan and review it with the people who own the system and the environment, then run in small steps, so that you trust the script, data and measurements before the full run.

  • Plan: scope, transactions and mix, load levels, profile, pass criteria and abort criteria, such as "stop if errors exceed 5% for two minutes".
  • Environment and data: production-like size and configuration, not shared during the run, monitored; enough distinct users and products for caches and unique constraints to behave realistically; payment or SMS providers stubbed or in their sandbox.
  • Permission: load only systems you own or have written permission to test, from separate generator machines, and tell operations before you start.
  • Smoke run, then full run: one or two virtual users for a few minutes prove that the script logs in, uses the data and gets correct responses; then a low-load baseline and the full profile while you watch the dashboards.
  • Evaluate and repeat: judge the steady state, repeat the run to confirm the result is reproducible, and record build, configuration, data and time window.

Try it: Load Test Data Generator Try it: Response Time Analyzer Try it: HTTP Request Benchmark

Worked example: an online store before a sale

Release 4.2 is tested before a seasonal sale. Expected peak: 100 requests per second last year × 1.2 growth = 120. The plan and the results of run 1 are in the block below; the tester reads them in this order:

  • Validity first: 119.6 requests per second achieved and the generator at 41% CPU, so the timings can be trusted.
  • Criteria: search and errors pass; checkout fails, with p95 at 1,140 ms against 800 ms.
  • Trend: checkout p95 started near 600 ms and climbed every minute at constant load, so checkout requests were queueing.
  • Report and confirm: a defect report with load level, window, metric, graphs and build. Developers trace it to the checkout service's database connection pool, capped at 20 connections; after the fix, the same profile and data run again (confirmation testing) and are compared with run 1.
Load test plan: online store, release 4.2, perf environment
Expected peak:  100 req/s (busiest hour last year) x 1.2 growth = 120 req/s
Mix:            search 70 %, product page 20 %, checkout 10 %
Profile:        ramp-up 0 -> 120 req/s in 10 min, steady state 30 min
                (minutes 10-40), ramp-down 5 min
Pass criteria:  search p95 <= 300 ms, checkout p95 <= 800 ms,
                error rate < 0.5 %, throughput >= 114 req/s
Validity:       load generator CPU < 80 %, response content checked

Run 1, steady state (min 10-40)   Target      Result      Verdict
  throughput                      >= 114      119.6       pass
  search p95                      <= 300 ms   210 ms      pass
  checkout p95                    <= 800 ms   1,140 ms    fail
  error rate                      < 0.5 %     0.2 %       pass
  load generator CPU (max)        < 80 %      41 %        valid

Common mistakes

  • Guessing the load ("let's try 1,000 users") instead of deriving it from production data and forecasts.
  • Starting at full load without a ramp-up and reporting the start-up spike as the system's performance.
  • Judging the whole run, ramps included, or setting the pass criteria after seeing the results.
  • Counting every HTTP 200 as a success, so fast error pages make the numbers look good.
  • Declaring a pass without checking that the planned throughput was reached and the load generator was not the bottleneck.
  • Running once, in a shared environment, without recording build, configuration and data.

The QA perspective

Load tests belong before releases with performance risk, before known peaks such as a sale, salary day or a registration window, and after changes to architecture, infrastructure or key queries; many teams also run a smaller load test regularly in the pipeline to catch regressions. The expected load comes from the product owner and from operations or analytics, the environment and monitoring from operations, and the criteria are agreed with the product owner and developers.

Ask early: what is the busiest hour we have seen, and what do we expect next? Which transactions matter most? What is acceptable at that peak? Which third-party services will receive traffic, and who must be told? Report a verdict per criterion with its evidence and the steady-state window; a failed criterion becomes a defect report with the load level, metric and graphs.

Practice exercise

Plan and judge a load test for a booking API

Your task

A clinic chain's booking API has two main transactions: searching free slots and creating a booking. The material below shows the busiest hour of the last three months and a first full run. The business expects 25% more traffic next quarter. Requirement: at the expected peak, slot search p95 ≤ 400 ms, booking p95 ≤ 1,000 ms and fewer than 1% failed requests.

Plan the load test, then decide whether the first run passed.

Material
Busiest hour, last 3 months (production analytics)
  GET  /api/slots       36,000 requests
  POST /api/bookings     7,200 requests

First full run, steady state window (minutes 10-40)
  achieved throughput        11.2 req/s
  slot search p95            280 ms
  booking p95                720 ms
  error rate                 0.4 %
  load generator CPU (max)   97 %
Steps
  1. Convert the busiest hour into the expected peak in requests per second, per transaction and in total.
  2. Sketch the load profile with the duration of each stage.
  3. Write the pass criteria, the validity checks and the window they apply to.
  4. List what to prepare before the full run.
  5. Judge the first run and decide what to do next.
Show the model answer
Model answer

Expected peak: slot search 36,000 / 3,600 = 10 per second and booking 7,200 / 3,600 = 2, so 12; with 25% growth, 12.5 and 2.5, which is 15 requests per second in total.

Profile: a smoke run first, then ramp up to 15 requests per second over 10 minutes, hold for 30 (minutes 10 to 40) and ramp down over 5.

Criteria on the steady state: slot search p95 ≤ 400 ms, booking p95 ≤ 1,000 ms, errors below 1%, counting bookings without a confirmation number. Validity: throughput at least 14.25 requests per second (95%) and load generator CPU below 80%.

Preparation: thousands of test patients and free slots so bookings do not collide, a reset between runs, the SMS provider stubbed, monitoring on, operations informed.

Verdict: inconclusive, not pass. Response times and errors are within the criteria, but the run reached only 11.2 of 15 requests per second and the generator ran at 97% CPU, so the generator was the bottleneck and may have distorted the timings. Add generator capacity and repeat.

Frequently asked questions

What is the difference between load testing and stress testing?

Load testing applies the expected load, up to the expected peak, and checks the pass criteria. Stress testing deliberately goes beyond that peak to find where and how the system breaks and whether it recovers. Some sources draw the line elsewhere: the Grafana k6 documentation calls a test at typical load an average-load test and treats load above the usual average as stress testing. State in your plan which levels you test.

How long should the steady state last?

Long enough to collect many samples of every transaction, including the rare ones, and to see whether response times and resource use are flat or trending. For a load test that is usually tens of minutes. If you need to know how the system behaves over many hours, that is a soak test.

Should I configure virtual users or requests per second?

Either works if you check the achieved throughput. With a fixed number of virtual users (a closed model), each one waits for its response before sending the next request, so when the system slows down the request rate drops and the run applies less load than planned. Tools can also target an arrival rate directly (an open model), for example the k6 arrival-rate executors or a JMeter throughput timer, provided enough virtual users are available to sustain it. Little's law, from the lesson on concurrent users and workload models, converts between users and rates.

Can I run a load test against production?

Only with explicit approval from the system's owners, a planned window, protection for real users and data, and the operations team watching. Most load tests run in a production-like test environment. Never load a system you do not own or have written permission to test, including third-party services that your system calls.

References

Practise with Mutqan tools

Generate concurrency test scripts (k6, JMeter JMX, Locust, Artillery, Node.js) with safe defaults for a target endpoint.

Automation

Generate performance test inputs with realistic distributions: think times, request mixes, payload sizes and ramp profiles.

Performance

Generate large parameter datasets (users, tokens, ids, payloads) for k6, JMeter, Gatling and Locust load tests.

Performance

Measure an endpoint's response time over several samples: min, max, average, median and p95.

Performance

Run a small, safe benchmark against a public endpoint (bounded requests and concurrency) and get throughput and latency percentiles.

Performance

Go deeper

Your progress on this topic

Part of the QA Roadmap