Guides »

Website Load Testing

Reading Time 29 Minutes
Last Updated 2024.07.04


We’ve all seen websites crash under a flood of traffic. Site crashes are notorious around marketing events like Black Friday and the Super Bowl, but they can strike year-round and for a variety of reasons, whenever an overloaded site can’t handle all the requests coming in.

When your site crashes under heavy traffic, it’s stressful for you and costly to your business. Customers turned away by the outage might never return. Even if your site stays alive but loads slowly or incompletely, the broken and sluggish experience will deter many users. People have short attention spans, and it only takes a few seconds to hit the back button and find an alternative.

The danger of site crashes is amplified by the fact that they always happen at the worst possible time, like during a launch or a big marketing campaign. Any website downtime is a problem, but when a site crashes under peak load it impacts the most users.

If your site is important enough that crashing under peak traffic is possible, it’s worth taking some steps to reduce your risk of downtime. Otherwise you’ll find yourself scrambling to bring your site back online after it gets slammed.

Preparing Your Site For Heavy Traffic

Predicting how many users your site can handle is difficult to impossible. A normally fast site can suddenly become slow and broken once a certain number of users visit concurrently. So how can you determine the breaking point?

It’s not enough to simply test how fast your website loads. Of course, you could test a single page load with tools like WebPageTest or Google Lighthouse, but that will only measure your site’s performance at baseline, when a few people are using it. Site speed tools are useful, but they don’t tell you how your site will perform when many people are hitting it at once. In other words, they tell you a lot about your site’s baseline performance, but very little about how well it can maintain this performance under heavy load.

To prepare for peak traffic, you’ll need to measure your site’s scalability. Scalability means its ability to deliver acceptable performance to many users at once. To measure this, you’ll actually need to test it with heavy traffic.

It would be impractical to recruit an army of human testers to all load your site at once to generate peak traffic conditions. Instead, you can use tools to simulate thousands of users interacting with your site the same way real users do.

The technique of simulating thousands of users on your site is called load testing (or stress testing), and load testing tools exist for this very purpose.

When Is Load Testing Your Site Worthwhile?

For important websites, even a brief period of downtime under peak traffic could cost vast amounts in lost business and reputation. Load testing can predict and prevent such crashes, so load testing an important site to prepare ahead of time is a smart investment. Of course, for smaller or non-critical sites, it might not be necessary.

By load testing your site with simulated peak traffic ahead of time, you’ll get a clear picture of how it will respond to real traffic when the time comes.

If your site crashes during the load test, it would almost certainly crash in real life under similar conditions.

But don’t worry! A site crashing during a load test is actually a good thing. It gives you advance notice of your site’s limitations and potential scalability bottlenecks, so you can address the limitations and fix any problems before they impact your real customers.

Load testing your site and tuning it to address any deficiencies will prepare it for heavy traffic. It takes a little effort, but you’ll gain the confidence and peace of mind that your site will perform well even in extreme traffic conditions.

Evaluating Load Testing Tools

The results from a load test are only useful if the test is a realistic simulation of your peak traffic conditions, and only insofar as the test results are measured and reported accurately.

Everyone’s tradeoffs in selecting a tool are a bit different, but here are a few things to consider so you get the best outcome from your load testing.

Simulating Realistic User Traffic

A load test needs to be realistic enough that from your website’s point of view it is just like thousands of real users are actually hitting the site. In an ideal load test, your site and servers shouldn’t even know the difference between the load test traffic and real traffic.

If your site is a trivial one-page static website, generating realistic traffic might be pretty easy. You can just load the home page over and over with many distributed bots (virtual users), and each page load impacts the server the same as a real site visit.

On the other hand, if your site is large and complex with many dynamic features (like a shopping cart, search bar, login and registration, account management, order processing, etc), then load testing is trickier but even more critical. Dynamic websites have more moving parts, including backend application servers and databases, so there are more potential scalability bottlenecks that could cause a crash under heavy load.

Load Testing with Real Browsers

Some load testing tools generate load at the protocol layer (automating a bunch of painstakingly scripted HTTP requests), while a few of the newer tools including Loadster can test with real web browsers (headless Chrome or Firefox web browsers).

Load testing at the protocol layer is suitable for HTTP APIs and even simple websites, but it can be challenging for complex websites and web applications that use client-side JavaScript or WebSockets or convoluted authentication flows.

Load testing with real browsers is the easiest and most realistic way to load test complex websites, even though real browsers are heavier and typically cost more than just firing off a bunch of HTTP requests. Real browsers do more of the work for you.

Measuring Response Times Under Load

Beyond simply generating load on your site, a load testing tool should also measure the site’s response times so you can see in real time if your site is running fast, bogging down, or altogether broken.

It helps to have a load testing tool that reports separate response times for each individual page or feature on your site, instead of just lumping the response times of all pages together into one big average. Outliers can easily be hidden in an average or aggregate.

It’s common in a load test for part of a site to perform normally, while another part of the site is broken. For example, a shopping site might as well be down if the home page loads but customers can’t add items to their cart or check out. It’s always a good idea to measure each page or action separately in your load test, so you can identify which parts are failing and don’t miss anything.

Handling Errors in a Load Test

If you load test any site with enough traffic, errors will result. The nature of these errors can tell you a lot about what is broken in the site and help you identify the bottleneck, or the slowest part of the system that is grinding everything else to a halt.

For example, socket timeouts or connection timeouts usually mean the network or the servers are saturated and can’t respond to incoming requests. The client waits for a certain amount of time and then times out.

Similarly, an HTTP 502, 503, or 504 error usually means that the server or load balancer is still answering requests, but is unable to service them because its backends are down or broken or overloaded. An HTTP 401, 403, or 404 error often means something is wrong in your load testing setup, like it might be using an invalid user login or trying to hit a page that no longer exists.

Other load test errors manifest more like functional errors but might still be load-related. Some dynamic sites return HTTP 200 OK responses, but the resulting web page is missing a section or has human-readable error messages displayed on it. This type of error is harder to test for because tools don’t interpret it automatically.

Some load testing tools allow you to add custom validation or assertions to your test script to evaluate the response content or body, to help you catch these sneaky on-page errors. For example, right after adding an item to your shopping cart, your load test script could look at the cart and validate that the item is really in there, throwing an explicit error if it’s not.

Load testing can also produce unforeseen errors that you might not have anticipated or handled in your script. It might not be clear at first what the problem is, so it helps to have a tool that captures as much detail as possible. This includes screenshots (if you’re testing with real browsers) as well as detailed error logs, request and response traces, the URL and method that generated the error, and overall context of where the bot was in the test script when the error happened.

Chasing down errors from a load test is one area where powerful tools can save you a lot of time.

Reporting and Sharing Test Results

A load test’s outcome is only as valid as the assumptions that went into it. These assumptions include what exact user behavior patterns you are testing, the number of concurrent users or total user visits simulated, the cadence in which the users arrive, and what kinds of response times and page load times and error rates are acceptable.

Afterwards, when your team and stakeholders ask how the load tests went, try to share as much information and nuance as possible. You wouldn’t simply want to reassure them that the site passed the load test… only to have it fail later in a real-life traffic spike.

To avoid instilling a false sense of confidence, or worse yet, getting blamed when things go sideways, you should always share load test results with as much detail as possible about the test outcome. Along with the detailed test results should be clearly documented assumptions that informed the behavior and load patterns that you tested.

In fact, all you can really safely say after a successful load test is that given this specific set of assumptions about user behavior and concurrency, the site met (or did not meet) your performance and scalability requirements.

Load testing tools vary widely in the scope and quality of automatically generated reports. Some tools generate reports with lots of interactive graphs and charts, while others take the view that the tester should process the data manually or store it into a time series database for further analysis.

Your Testing Budget (Time and Money)

All load testing projects are limited by some combination of time and money. Sometimes time is the scarcer resource.

Your time budget might be explicit if you’re facing a deadline, or it may be flexible if your company just wants to get useful results sooner or later. In either case, few of us want to make it our life’s work to fiddle around with load testing tools and frameworks.

Of course, it’s possible to run load tests for no more than the cost of the cloud instances and bandwidth. There are several free and open source tools that are highly flexible. That said, if you have budget to spend on load testing tools that do more of the chores for you, you’ll likely get to a successful outcome in less time.

Shortening the testing feedback loop is crucial because load testing websites is an iterative process. You’ll need to run a round of load tests, analyze and interpret the results to determine the bottleneck, make changes to your site based on your findings, and load test again. You might need to repeat your tests many times in quick succession, so if your tool can eliminate chores between iterations it can greatly accelerate the process.

Gathering Website Load Testing Requirements

Sometimes it’s okay to run load tests without a specific requirement, just to explore how your website responds to increased load. Exploratory load testing can be a helpful way to approximate the “breaking point” at which your site can no longer take additional traffic.

But in most cases you’ll be load testing in preparation for a high traffic event, so it helps for you and your colleagues to be on the same page about what the load test should simulate, how much traffic it needs to generate, and what response times and error rate are acceptable.

Assumptions About Website Visitor Behavior

For the load test to be realistic, the steps your bots take through the site should accurately mimic the behavior of real users.

Obviously, a load test that only hits the home page will not test the impact of users adding items to their carts and completing orders. A load test that just hammers a single URL over and over won’t be equivalent to a test that loads the full page with all internal and 3rd party page resources. A load test that simulates anonymous users won’t have the same impact on your servers as a load test where every bot is logged in as a different user.

Load testing requirements aren’t complete unless they describe the specific user behaviors to be simulated in the load test. Make sure your assumptions about real user behavior are documented and well-represented by your tests.

Site Analytics Data (Visitors, Visits, and Concurrent Users)

You probably have some kind of website analytics or logging in place already, so you know how much traffic your site experiences day-to-day. With these analytics tools you can look back at historical usage and find your busiest day or even your busiest hour to date. Perhaps you can hazard a guess at future usage trends based on past usage.

If at all possible, your analytics data should inform your load testing requirements, but it’s not always straightforward. You’ll need to convert the site visitor rates into “concurrent bots” or “virtual users” or “peak users” which are the terms that most load testing tools use.

You might need to work backwards to figure out the number of concurrent users your tool will need to simulate. For example, if your test script simulating a site visit takes 3 minutes (1/20th of an hour) and you know from your analytics that the site had 5000 visits per hour, your load testing tool will need to run approximately 250 bots ( virtual users), each executing your script over and over, to achieve a rate of 5000 iterations per hour.

When you’re interpreting your site analytics data, keep in mind that the rate of site visits is probably not constant! Just because there were 5000 unique site visits in an hour doesn’t mean there were 83 visits every minute. Rather, it’s much more likely there were peaks and valleys throughout the hour, and your site took much more traffic at the busier minutes than at the quieter minutes. If your analytics tools can only tell you visitor data in hourly or daily resolution, make sure to pad your site traffic assumptions to allow for fluctuations.

Whatever load testing requirements you derive from your visitor data, make sure to share them widely with your team and stakeholders! If you work with a product manager or a client, get them to provide the final sign-off on whatever traffic requirements you are plan to load test. Otherwise, you as the tester risk your assumptions being wrong if the site later crashes in production. Even if you work in a friendly and blame-free organization, your colleagues might have valuable insights about site usage that can help inform your requirements.

Performance & Error Rate Acceptance Criteria

What page load times and response times are deemed acceptable for your site? This varies depending on your business, your users, and what they are trying to accomplish.

It’s during a customer’s first contact with your site or brand that they are especially sensitive to slowness and errors. If site visitors are browsing for a new product or service and your site is slow or broken, they’ll simply move on.

If you have a more captive audience, like SaaS customers who are already paying for your service, you may have a little more leeway around temporary slowness… however, this type of customer rightfully has high expectations of your service since they are paying for it, and you could lose them if you don’t deliver a good experience.

When you begin load testing, it’s helpful to consider what level of performance is acceptable for your site under peak load. Include this threshold in your load testing requirements. Here are a few examples of how a performance requirement might be phrased:

  • The average response time must not exceed 750ms
  • The 95th percentile page load time (p95) must not exceed 2.5 seconds
  • The Shopping Cart must load fully in a median (p50) load time of 1.0 seconds
  • Final checkout submission should never take more than 5.0 seconds

Similarly, think about what types of errors are acceptable (if any) and what error rate is acceptable under peak load. Here are a few examples of how that requirement could be phrased:

  • The overall request error rate must be less than 0.1%
  • There should be no socket timeouts or connection timeouts
  • No errors are acceptable

If in doubt, treat all errors as a requirements failure and aim for an error-free load test.

The key to writing load test acceptance criteria is that it should address the things that really matter (performance and stability), and that all acceptance criteria should be testable with a pass/fail outcome.

Website Load Testing Requirements Checklist

To recap what we’ve covered on load testing requirements, here is a short checklist you can use to make sure your requirements are thorough and testable.

  • My requirements describe the specific user behavior(s) to be tested in a way that my team members and I can clearly understand.
  • If multiple user behaviors are to be tested simultaneously, the requirements say what percentage of users are doing each behavior.
  • My calculation of how many concurrent bots (or virtual users) are needed is correlated to transaction throughput, visitor throughput, site visits in a period, or some other relevant throughput metric.
  • Requirements include acceptable performance thresholds under peak load, in terms of response times (as an average, median, percentile, or other aggregate).
  • My requirements specify what error rate, if any, is acceptable under peak load.
  • All the thresholds and criteria are testable with pass/fail outcomes.
  • I've shared the load testing approach and acceptance criteria with colleagues, stakeholders, clients, etc.

As a tester, being explicit about these requirements and sharing them with your colleagues is a good way to make sure you are testing the right things in a methodical manner.

Sharing requirements is also (for lack of a better term) a good way to “cover your ass” so you aren’t blamed if the site crashes in production because you tested the wrong requirements.

Configuring Load Test Scripts and Scenarios

Different load testing tools use different terminology for key concepts, but they are mostly analogous.

In this guide, we’ll use the word script to describe the steps an individual bot (or virtual user) takes when interacting with your site. We’ll use the term scenario to describe the recipe for assembling groups of bots into a load test.

Load Test Scripts

Scripts are executed by a bot (or virtual user) to generate test traffic against your site. Typically, a script should mimic the steps that a real user would take.

Before you even create your load test scripts, you might want to scribble down what steps matter for testing your site. For simple websites, there might just be a single thing that all users do. For more complicated sites and web applications, there could be multiple important user flows, each deserving of its own script.

Here are some examples of user steps for different types of sites.

  • Home page -> exit
  • Home page -> submit contact form -> exit
  • Home page -> click login button -> fill out login form -> view dashboard -> click open order -> track order -> log out -> exit
  • Home page -> search for a product -> view search results -> click a search result -> add to cart -> view cart -> checkout -> confirmation page -> exit

Of course, the above are just human readable steps and not yet any kind of executable script, but they are in a concise format for sharing with human stakeholders to make sure you’re on the same page.

When it comes to creating the actual executable script, every load testing tool is different. Some tools like Loadster have a browser extension that can record you stepping through your website in a new browser tab and turn that into a recorded script. Other tools use various programming languages or YAML files for manual scripting.

Once you have an executable script, run it with a single user or a small batch of users to make sure it works reliably before starting a load test. This is a quick way to work out bugs in your script itself without the time and expense of running a bigger load test.

Load Test Scenarios

A load test scenario is kind of like a test plan. It tells how many groups of bots (virtual users) should run in the load test, how long they should run for, what script each bot group should be executing, and so on.

When you create your load test scenario, it should be based on the load testing requirements you are trying to test.

Take into account the intended user behavior when deciding how many bots should run each script. For example, if you’re load testing a big e-commerce site, you might want 70% of users to be just browsing, 10% adding items to their cart and abandoning it, 10% adding items to their cart and completing checkout, 5% searching for a specific item using the search bar, and 5% managing their account and viewing order status. In a load test scenario, each of these behaviors can be tested simultaneously by appropriately-sized groups of bots. Of course, for simpler sites you might only need a single group of bots all doing the same thing.

Think about the script duration and whether it correctly mimics a real site visit. For example, if your average site visitor takes 6 minutes, add wait times between the steps in your script so a bot takes about 6 minutes to do the same thing.

Using realistic wait times in your script creates a more accurate simulation, and also makes it easier to achieve the right cadence and throughput in your load test. Based on the duration of your script you can calculate how many bots you need to produce the right number of visits (script iterations) in a period.

It usually takes a little trial and error to get the distribution of bots and the cadence just right, so you might need to run a few smaller tests to check your configuration before scaling up.

Load Test Datasets

Most load testing tools can pull dynamic data from a dataset so that each bot submits different values each time. Datasets are useful if your site has a login feature, a search field, many different products for sale, etc.

For dynamic sites, making all bots use the same account or search for the same thing or purchase the same product could result in an inaccurate load test because your site might cache the data. Or it might break the load test altogether because the bots would all be making changes in the same user account and tripping over each other.

Once you’ve created a dataset and filled it with whatever dynamic values you need (like a set of usernames and passwords, for example), you can bind it to your load test script and reference the values with variables. Of course, different tools have different approaches for mapping the dataset to the script, but the concepts are broadly similar.

Running Load Tests on Your Site

As soon as you have a working load test script, it’s tempting to run a load test with the maximum amount of load at once. You could do it this way, but often it’s better to start smaller and work your way up.

Running short preliminary load tests helps you confirm whether your scripts and scenarios are working before you incur the costs of running a bigger test. The preliminary tests might also reveal problems with your site that you can fix before going for the big one.

When you’re ready to run a longer test, it’s often a good idea to ramp up the bots gradually. A linear ramp from zero to maximum bots over 10 minutes or longer can often tell you at what point your site starts having problems. If you just go for the maximum load immediately, without a gradual ramp up, the site might either pass or fail but you won’t know the breaking point.

After preliminary tests have validated your test scripts and configuration, and you have a decent notion that your site will handle the load, you can go ahead and run a full-scale load test to validate your acceptance criteria.

Analyzing Load Test Results

When you run a test, the load testing tool will typically show you performance metrics in real time or close to real time. These metrics include things like:

Response Times

Aggregated response times (average, maximum, minimum, p50, p95, etc) tell you how fast your site is responding to the load testing tool. Since your load test acceptance criteria has to do with response times, this is an important section.

If the load testing tool is reporting fast response times at the average and 95th percentile, in the absence of errors, it’s likely that your site is handling the load pretty well. If response times get unacceptably high, the site is probably overloaded and needs changes before it can handle the amount of traffic the tool is generating.


A good load testing tool will surface any errors it detects while running the test. These can include errors from different layers, such as:

  • Socket errors from TCP, like socket timeouts, connection timeouts, connection resets, etc.
  • HTTP error status codes such as 403, 500, 503, etc.
  • Script errors like if the bot couldn’t find the next element that it was supposed to click on.
  • Validation errors, which might require special effort on your part to enable but are often worth doing (like making sure the word “Success” appears on the order confirmation page, and so on).
  • Internal errors from the load testing tool itself, which normally shouldn’t happen but are certainly worth investigating if they do.

Watch the error count and error breakdown closely while a load test is running so you can stop the test if it’s failing badly.


The concept of throughput in a load test can refer to quite a few different things, like iteration throughput, transaction throughput, or network throughput.

If your load testing tool reports on Iterations you can watch this number so you know how many times a bot has executed your script from start to finish. The number of iterations in a load test is equivalent to the number of distinct visits or user journeys on your website. If you have a requirement to simulate a certain number of visits in a time period, watch the Iterations count in your load test to make sure it’s simulating the right number of visits.

At the transaction level, you can watch the number of requests (Hits) or page views (Pages) to get a more precise count of interactions with your site. These metrics are easy to correlate with your website analytics tool so you can compare the load test with real world usage patterns.

At the network level, many tools will tell you how many bytes have been transferred (upload and download) and a rolling average of bytes per second or bits per second, so you can tell how busy the network is and whether it might get saturated under heavy load.


Not all load testing tools produce graphs, but if you’re lucky enough to be using one that does, you can use these to view how the metrics changed at specific times throughout the test.

For example, you could use a Response Times graph to see your site’s average response time (possibly broken down by unique URL) as the test progressed, so as to tell if the site became slower under sustained load.

You might also want to correlate multiple graphs so you can see the relationship between different metrics. For example, you could overlay the Running Bots graph with the Response Times and Errors graphs to see how the response times and error rate increased as more bots ramped up.

Graphs can also be a great way to notice spikes or anomalies that happened during the test that might be hidden in an overall average or aggregate.

Evaluating Load Test Acceptance Criteria

After a load test finishes, you can review the test report to see if the results met the acceptance criteria you were testing for.

First of all, examine whether whether the load test simulated the right amount of load on your site, by counting the total number of iterations for each script or bot group. If it’s lower than planned, it means the site wasn’t tested with the intended amount of throughput. If it’s higher than planned, maybe your load test pushed the site a little too hard. Don’t be surprised if you have to run a few tests and apply a little trial and error to dial in the throughput.

Compare the response time aggregates (average, maximum, minimum, p50, p95, etc) with those in your requirements. If your requirements were stated in a testable manner, it should be easier to say with certainty whether the metrics from the load test pass or fail the acceptance criteria.

Similarly, you can review the breakdown of errors (if any) from your load test and cross-check that with your acceptance criteria.

If your load test acceptance criteria was clearly stated, you should be able to arrive at one of the three outcomes after each load test:

  1. RETRY - Didn’t test the requirements (too few bots, too many bots, wrong traffic mix, broken scripts, etc)
  2. FAIL - Accurately tested the requirements and the site failed (too slow, too many errors)
  3. PASS - Accurately tested the requirements and the site passed (fast and error-free)

Again, load testing websites is an iterative process, so don’t get too frustrated with any particular outcome. It sometimes takes a few tests to get everything right.

Strategies for Improving Website Scalability

If your load testing determines that the site falls short of the performance and scalability requirements, what next? Usually it depends on where the bottleneck is in the first place.

Frontend Performance Tuning

Even though website scalability bottlenecks occur on the server, it’s a good idea to reduce the load by optimizing frontend performance as much as possible. Fewer and smaller requests to your servers mean less load on the server.

First, see if you can eliminate unnecessary dependencies from your site altogether. If you’re loading a JavaScript library that is no longer needed in modern browsers, maybe you can drop it altogether. If your CSS is bloated, consider slimming it down. If your site has superfluous images that do nothing for the end user, remove them or reduce their size.

Second, make sure your site sets appropriate cache headers. If a piece of content or a media file rarely changes, allow the browser to cache it so it doesn’t result in too many requests to your servers. These little requests can really add up when they’re repeated unnecessarily on every page load.

Third, see if you can offload cacheable resources (images, JS, CSS, etc) to a CDN or a caching reverse proxy or WAF, so your servers don’t work as hard to serve them. This will only help if you’ve already set appropriate cache headers to indicate what is cacheable.

Of course, when it comes to eliminating backend bottlenecks, frontend performance tuning only goes so far… but it does help to improve the baseline user experience while also lessening the incremental load on your servers from each concurrent user.

Backend Performance Tuning

Scalability bottlenecks can occur at any point in the system, by limiting throughput. Bottlenecks have a non-linear impact on your site’s performance: it might be fast and efficient up to a certain amount of load, and then slow to a crawl once the bottleneck becomes saturated.

Hard bottlenecks are things like the CPU, memory, disk, and network. These are physical (or virtual) limitations on the underlying machinery that powers your site. All sites are served by a finite amount of hardware, even if it’s buried under layers of abstraction, and when these finite limits are reached a site can no longer service additional load.

Soft bottlenecks are things like database connection pools, TCP connections, server threads or workers, process heap memory, queues, asynchronous background workers, and so on. They are implemented in software but nonetheless they restrict your site’s ability to handle additional requests beyond a certain rate. The nature of these soft bottlenecks depends on your stack and the design of your site. A simple web server serving static files has at least a few potential soft bottlenecks, while a complicated web application might have hundreds.

Backend performance tuning is easier if you have some kind of application performance monitoring tool, so you don’t have to guess at what your site’s scalability bottleneck might be. Observing an APM tool while your load tests run can help you pinpoint the bottleneck faster and more accurately than guessing through trial and error. Of course, hard limits like CPU and memory are easy to monitor at the OS level with tools like top for Unix/Linux or perfmon for Windows or other built-in tools for other platforms, but for soft limits it helps to have an APM tool or custom instrumentation that fits with your technology stack and application.

When you’re tuning a website or web application for the first time, the bottleneck is more likely due to a soft limit ( configuration) than a hard limit (physical resources).

An initial goal of backend performance tuning should be to remove all soft bottlenecks until a hard bottleneck is reached. Once the load test maxes out hardware resources like CPU, and your software is working efficiently, you can think about scaling the environment.

Scaling Vertically and Scaling Horizontally

Scaling a hosting environment typically means bigger servers or more servers, or some combination of the two. Replacing the servers with bigger ones with more resources is called scaling vertically or scaling up, and adding more servers to help share the load is called scaling horizontally or scaling out.

Should you scale up or scale out? It depends.

Scaling Up Vertically

Scaling up is usually simpler than scaling out, if you can get away with it. To scale up you just move to a bigger version of the same server with more resources.

For example, if you’re running on AWS EC2 and hit a CPU bottleneck, you could just move from a c5.large to a c5.xlarge to double your CPU. This is a straightforward way to address a CPU bottleneck.

Beware of assuming you can always double your CPU and it will double your throughput! Even if CPU was the initial bottleneck, there might be another bottleneck (hard or soft) lurking right behind it. For example, you might double the available CPU but only achieve a 10% increase in throughput, because you then start maxing out your database connections with just a little more load.

You should always load test again after scaling up an environment to make sure the upgrade resolved the bottleneck (and discover the next bottleneck).

Scaling Out Horizontally

Scaling out works well with most websites and many web applications, but it is more complicated than scaling up because now you need a way to distribute the load between multiple servers.

If you have two or more servers, you’ll need a load balancer to route incoming requests to one of the servers. For serving a static site, the load balancer doesn’t need to be very sophisticated, because it can forward any request to any server and it will get handled. But for web applications that store some kind of user state on the server, the load balancer will need to be aware which user each request belongs to and send it to a server instance that knows about that user.

In general, try to design your web applications so that the requests are stateless so it doesn’t matter which server they get sent to. This will make scaling out easier.

Although horizontal scaling is more complicated than vertical scaling, it can also add redundancy if done right because now you have multiple server instances available to service requests.

The big cloud platforms offer virtual load balancers and autoscaling features that make scaling out much more approachable than it used to be.

Get Started With Load Testing

Load testing a website is an iterative process that requires load testing tools to simulate the traffic. To recap, if you’re ready to get started…

  1. Nail down your load testing goals and your performance and scalability requirements, working closely with your colleagues if possible.
  2. Select a load testing tool and start scripting, preferably without spending much money until you know if the tool will work for you.
  3. Run initial exploratory load tests to validate your testing setup, so you know if your scripts and scenarios and datasets are working to simulate the right traffic conditions.
  4. Run larger load tests to test your performance and scalability requirements.
  5. Analyze the results to see if your site passed or failed the load test.
  6. If the site failed the load test, make changes to the site and environment and test again.

Hopefully this guide helps you with load testing your website, but the rabbit holes sometimes go deep and we’ve barely scratched the surface in some areas! We’d like to hear from you at if you have any follow-up questions or ideas how this guide could be better.