Skip to main content
Load testing software performance under increasing user traffic
Sten Laidoner
Sten Laidoner|July 9, 2026|Reading time: 13 min read

What Is Load Testing?

A practical introduction to load testing, including important performance metrics, realistic traffic patterns, test preparation and common mistakes.

Load testing is a type of non-functional testing used to understand how an application behaves when many users or requests hit it at the same time.

Instead of checking whether a feature works correctly for one user, load testing asks a different question: what happens when hundreds, thousands or even millions of users try to use the system?

A load test simulates expected traffic and measures how the application responds. Typical areas to monitor include response time, throughput, CPU usage, memory, network activity, disk usage, error rate and concurrent user capacity.

The goal is not simply to make the system busy. The goal is to understand when performance starts to degrade and whether the application can handle the level of usage the business expects.

Why is load testing important?

Imagine an online store preparing for a major sale. The company spends weeks promoting the event, ads are running, customers know the date and the discounts are ready.

The campaign goes live and thousands of people arrive at the website at the same time. Then the site stops responding.

Some users see `HTTP 503 Service Unavailable`. Others wait for pages to load. Payments fail and customers leave.

The marketing campaign worked. The system did not.

This is one of the clearest reasons load testing matters. Performance problems are not always visible during normal development or functional testing.

A page may load perfectly with 10 users and still become unusable with 10,000. Load testing helps teams find these limits before real users do.

Load testing is about behaviour under pressure

A load test studies how a system behaves as demand changes. The test may begin with 100 users, increase to 1,000, then 10,000 and eventually 50,000.

The system may perform well at first. As traffic increases, response times may slowly rise. At another point, CPU usage may reach its limit, database connections may become exhausted and requests may start timing out.

Eventually, the application may fail.

The exact point where behaviour starts to change is important because it helps teams understand:

  • Expected operating capacity
  • Performance limits
  • Scaling needs
  • Infrastructure risks
  • Release readiness

Load testing can also be useful after significant product or infrastructure changes. New features, major code changes, database updates, caching changes, architecture changes or migration to a new hosting environment can all change how the application behaves under pressure.

A system that handled traffic well six months ago may perform very differently after several releases.

Load testing and performance testing

Load testing is part of the wider performance testing area. The terms are sometimes used interchangeably, but they are not exactly the same.

Performance testing is the broader category. It looks at how fast, stable and scalable a system is. Load testing specifically focuses on expected or increasing user load.

Other common performance testing approaches include:

  • Stress testing: Increase load until the system reaches or exceeds its limits.
  • Spike testing: Introduce a sudden and significant increase in traffic.
  • Endurance testing: Keep the system under load for a longer period of time.
  • Scalability testing: Check how performance changes as resources or demand increase.

For example, load testing may check whether the system can support 10,000 concurrent users. Stress testing may continue increasing that load until the application fails.

Spike testing may suddenly increase traffic from 1,000 users to 20,000, while endurance testing may keep the system under load for several hours or days.

Each technique answers a slightly different performance question.

Important load testing metrics

A good load test produces more than one number. Looking only at the total number of users is rarely enough because several metrics need to be analysed together.

A system can return requests quickly while failing half of them. It can maintain a low error rate while response times become unusable. The wider performance picture matters.

Response time

Response time measures how long the system takes to answer a request.

Imagine a user clicking the login button. Under normal conditions, the request may complete in 300 ms. Under heavier load, it may increase to 2 seconds and later reach 10 seconds.

The request still technically succeeds, but the user experience has clearly degraded.

Average response time can be useful, but teams should also review percentiles such as p90, p95 and p99.

A good average can hide a smaller group of users experiencing very slow responses. For example, most users may receive a response in 200 ms while a smaller group waits several seconds.

Percentiles help show how the slower part of the user base is actually experiencing the system.

Throughput

Throughput measures how much work the system can process during a period of time.

This may be measured as requests per second, transactions per second or bytes per second.

For example, a service may process 500 requests per second. That number is not automatically good or bad. It needs to be compared with the expected business load.

A small internal tool may never need high throughput. A payment API or large marketplace may have completely different requirements.

CPU usage

CPU usage shows how much processing capacity is being consumed. If CPU usage reaches or remains close to 100%, the system may struggle to process new work.

High CPU usage can lead to slower responses, request queues, timeouts and service instability.

However, low CPU usage does not automatically mean the system is healthy. The real bottleneck may be the database, network, storage or an external dependency.

Memory usage

Memory should be monitored throughout the test, especially during longer test runs.

A common performance problem is memory usage that gradually increases:

  • Start → 35%
  • After 1 hour → 55%
  • After 3 hours → 78%
  • After 6 hours → 96%

This may indicate a memory leak or poor resource cleanup.

A short load test could completely miss the problem because the system may appear healthy during the first few minutes.

This is one reason endurance and longer-running load scenarios can provide very different information from short performance checks.

Network usage

Network limits can become a bottleneck when large amounts of data are transferred. This is especially relevant for file uploads, video, images, large API responses and other data-heavy applications.

The application itself may be working correctly while the available bandwidth becomes the limiting factor.

Disk and database activity

Applications often depend heavily on databases and storage. Under load, teams may see slow database queries, connection pool exhaustion, lock contention, high disk I/O or slow writes.

A frontend may appear slow even when the actual bottleneck is a database query several services deeper.

This is why load testing results need technical investigation, not only a graph showing response time.

Error rate

Error rate shows how many requests fail.

For example:

  • 10,000 total requests
  • 100 failed requests
  • Error rate → 1%

Errors may include HTTP 500, 502 or 503 responses, timeouts, connection failures and application-level errors.

The interesting question is often when the failures begin.

If no errors occur with 5,000 users but failures start at 7,000, the team has identified an important capacity point.

Concurrent users

Concurrent users represent users actively interacting with the system during the same period. This is different from the total number of registered users.

An application may have one million accounts but only 5,000 active users at the same time.

Load models should be based on realistic concurrency. Testing one million concurrent users simply because the product has one million registered users may create a completely unrealistic test.

Common load testing patterns

Real users do not always arrive at the same speed. Different load patterns can help teams simulate different types of traffic and understand how the application behaves during each one.

Steady load

A steady load keeps the number of users relatively constant.

For example, the system may run with 1,000 users for 60 minutes. The load remains stable throughout the test.

This is useful for measuring normal expected traffic and can also help identify gradual resource problems.

Ramp-up load

Ramp-up testing increases the load gradually over time.

For example:

  • 0 minutes → 100 users
  • 15 minutes → 250 users
  • 30 minutes → 500 users
  • 45 minutes → 750 users
  • 60 minutes → 1,000 users

This makes it easier to see where performance begins to change.

Response times may remain stable until 500 users. After 750 users, database usage may increase sharply. At 1,000 users, errors may begin.

That pattern tells the team much more than simply starting the test at maximum load.

Ramp-down load

Ramp-down testing gradually reduces the number of active users.

For example:

  • 1,000 users
  • 750 users
  • 500 users
  • 250 users
  • 100 users

This can help answer an important question: does the system recover when demand decreases?

Imagine CPU usage reaches 95% under heavy traffic. The number of users then drops by half, but CPU usage remains at 95%. That may indicate the application is not releasing resources correctly or that a background process continues consuming capacity.

Recovery behaviour is often just as important as the initial failure point.

Spike load

A spike represents a sudden increase in traffic. The application may move from 500 active users to 15,000 in a very short period of time.

This may happen because of flash sales, breaking news, ticket releases, product launches, marketing campaigns or sudden social media exposure.

Spike tests help show how quickly the system can react to unexpected demand and whether scaling or protective mechanisms respond fast enough.

Creating a realistic load test

A load test should not simply repeat one request as quickly as possible. Real users behave differently, and a realistic test should try to reproduce actual user activity.

Imagine an online store. A real user may:

  • Open the homepage
  • Search for a product
  • Open a product page
  • Add an item to the cart
  • Wait and compare information
  • Open the cart
  • Start checkout
  • Enter payment information
  • Confirm the order

These actions create different requests and different load across the system.

A realistic load model should reflect important user journeys rather than hammering one endpoint with traffic that production users would never create.

Think time

Real users do not click every button instantly. They stop, read, compare products and enter information.

Think time simulates the delay between user actions.

For example:

  • Open product page
  • Wait 8 seconds
  • Add product to cart
  • Wait 15 seconds
  • Start checkout

Without think time, a load script may send requests much faster than a real user ever would. This can produce an unrealistic load model and misleading results.

Correlation and dynamic data

Modern applications often generate temporary or dynamic values such as session IDs, authentication tokens, CSRF tokens, transaction IDs and request IDs.

A recorded script may contain a session value such as `session_id=abc123`. That value may no longer be valid when the script is replayed.

The test needs to capture the new value and use it in later requests. This is often called correlation.

Without proper correlation, the load test may fail because of invalid test data rather than an actual performance problem.

Data parameterisation

Not every virtual user should use exactly the same data.

Imagine testing a login flow with 1,000 users. Using one account for every virtual user may create behaviour that is completely different from production.

Instead, test data could include:

  • user001@example.com
  • user002@example.com
  • user003@example.com
  • Different users, roles and account states

Each virtual user can receive different credentials or test data.

Parameterisation makes test scenarios more realistic and can prevent caching, locking or session behaviour from distorting the results.

Iterations

An iteration represents how many times a scenario is repeated.

For example, 100 virtual users running 10 iterations each results in 1,000 total scenario executions.

Iterations should follow the expected usage pattern. A user may log in once but search for products twenty times.

Different actions should not automatically use the same repetition settings.

Preparing for test execution

Load testing requires preparation. Running the script is often the easiest part.

The environment, test data and monitoring need to be ready before the test starts.

Use a realistic environment

Ideally, the load testing environment should be close enough to production to provide meaningful results.

Important areas include server configuration, database size, caching, infrastructure, service limits and network configuration.

Running a load test against a very small test environment may produce results that cannot be compared with production. At the same time, production testing carries obvious risk.

The environment and test scope need to be planned carefully.

Prepare load generators

Load generators create the virtual user traffic. A large test may require several machines.

The load generator itself must not become the bottleneck.

Imagine the application is healthy but the machine generating traffic reaches 100% CPU. The results may suggest that the application cannot process more requests when, in reality, the testing tool simply cannot generate them.

Load generator health should also be monitored.

Warm up the system

Some applications behave differently immediately after starting. Caches may be empty, connections may need to be established and services may still be initialising.

A short warm-up load can help the system reach a more normal operating state before measurements begin.

Prepare monitoring

Before starting the test, make sure the required metrics are visible.

That may include:

  • Application response times
  • CPU
  • Memory
  • Database connections
  • Database query time
  • Network
  • Disk
  • Error logs
  • Service metrics

Discovering after the test that an important metric was not recorded is frustrating because the entire test may need to be repeated.

Load testing and observability should be prepared together.

What happens after the load test?

The real work starts when the test finishes.

Save the raw results, keep the logs, export important metrics and document the test configuration. Then compare how the system behaved at different levels of load.

For example:

  • 1,000 users → p95 450 ms → 0.1% errors
  • 5,000 users → p95 1.8 s → 0.8% errors
  • 8,000 users → p95 7.2 s → 12% errors

The system clearly begins degrading somewhere between 5,000 and 8,000 users.

The next step is investigation. Did CPU reach its limit? Did database queries slow down? Were connections exhausted? Did an external service begin failing?

Load testing should lead to technical questions. The graph alone is not the result.

Common load testing mistakes

Load testing can produce very convincing graphs and still provide misleading information if the scenario itself is wrong.

Several mistakes appear repeatedly.

Testing unrealistic traffic

A common mistake is choosing a large number because it sounds impressive.

Let's test one million users.

Why? Is one million concurrent users realistic? Does the product expect that traffic?

A useful load test should be based on expected usage, growth targets or known traffic peaks.

Looking only at averages

An average response time of 500 ms may look good.

But imagine:

  • 90% of users → 200 ms
  • 10% of users → 3.2 seconds

The average hides the problem.

Percentiles and response-time distribution matter.

Ignoring failed requests

A system may appear fast because it is rejecting requests.

For example:

  • Average response time → 100 ms
  • Error rate → 60%

That is not good performance. The application is failing quickly.

Performance and correctness must be analysed together.

Testing only the happy path

Real load is distributed across different features. Users may log in, search, upload files, make payments, refresh data and update profiles.

Running 100% of the traffic against one endpoint may not represent the actual system.

Important business flows should be represented according to realistic usage.

Forgetting external dependencies

Applications often depend on third-party services.

The application may handle 20,000 users while the payment provider allows only 500 requests per second.

The bottleneck may exist outside the application.

Rate limits, external dependencies and integration behaviour should be understood before the test.

Using production-sized load without production-sized monitoring

Heavy traffic without proper monitoring creates very little useful information.

You may know that the system became slow, but you still will not know why.

Load testing and observability need to work together.

The tool is important, but the quality of the test scenario matters more.

A powerful load testing tool running an unrealistic script will still produce misleading results.

Load testing should reflect real risk

Load testing is not about proving that a server can survive a large number on a dashboard. It is about understanding how the product behaves when real demand increases.

The best load tests are based on realistic user behaviour, expected traffic and important business flows.

Monitor response times, watch the infrastructure and understand where failure begins. Most importantly, investigate why performance changes.

A system working perfectly for one tester does not tell you how it will behave when thousands of users arrive at once.

That is exactly the question load testing is designed to answer.

Need practical QA support?

Laidoner Solutions helps software teams with manual QA, API testing, localization review, release checks and clear defect reporting.

Contact Us