Website Load Testing: How to Test Your Site Before a Traffic Spike
Founder and Tech Writer, CodeNexon
Key Takeaways
- ▪Speed tests measure one visitor. Load tests measure many at once.
- ▪Estimate concurrent users from peak-hour sessions times session minutes, divided by 60.
- ▪Watch the 95th percentile response time and the error rate, not the average.
- ▪Only load test sites you own, and check your host's acceptable use policy first.
In this guide
Website load testing means sending a controlled amount of simulated traffic to your site to see how response times change as visitors increase, and at what point things start to fail. For a small business, the useful question is simple: can my hosting handle a busy day, such as a sale, a newsletter send or a mention in the press? You can answer it for free with an open-source tool such as k6, running a test from your own computer against a staging copy of your site, ramping from a handful of virtual users up to your expected peak and watching the 95th percentile response time and error rate.
This guide explains what to measure, how to run a first test with k6 step by step, how to read the results, and the rules that keep load testing safe and within your host's terms.
Load testing vs speed testing
People often mix these up.
| Speed test | Load test | |
|---|---|---|
| Tools | PageSpeed Insights, WebPageTest, Lighthouse | k6, JMeter, Locust and similar |
| Visitors simulated | One | Many at once |
| Question answered | How fast is a page for one visitor? | How does the site behave as visitors pile up? |
| Typical finding | Large images, slow scripts, poor caching | Server running out of CPU, memory, PHP workers or database connections |
A site can be fast for one visitor and fall over at 50 at once. Speed testing finds problems in the page. Load testing finds problems in the server and its configuration. For the single-visitor side, see Core Web Vitals Explained and What Is TTFB?.
The types of load test
| Test | What you do | Answers |
|---|---|---|
| Smoke test | 1 to 5 virtual users for a minute | Does the script work, and is the site healthy at all? |
| Load test | Ramp to your expected normal peak, hold, ramp down | Is performance acceptable on a normal busy day? |
| Stress test | Keep increasing past the expected peak | Where is the breaking point, and how does it fail? |
| Spike test | Jump suddenly to a high level, then drop | Can it absorb a sudden burst, such as an email send? |
| Soak test | Moderate load for several hours | Do memory leaks or slow build-ups appear over time? |
For a first test on a small business site, run a smoke test and then a load test. Add a spike test if you send newsletters or run promotions that bring visitors all at once.
What to measure
Response time percentiles
Averages hide bad experiences. If 95 requests take 200 milliseconds and 5 take 6 seconds, the average looks acceptable while one visitor in twenty waits six seconds. Load testing tools report percentiles:
| Metric | Meaning |
|---|---|
| p50, the median | Half of requests were faster than this |
| p90 | 90% of requests were faster |
| p95 | 95% of requests were faster. A common target metric |
| p99 | 99% were faster. Shows the worst experiences |
A reasonable target for a content site's HTML pages is a p95 under about 800 milliseconds, which lines up with Google's guidance for Time to First Byte of 0.8 seconds or less. Set your own target based on what your site does.
Error rate
The share of requests that failed or returned an error status such as 500, 502, 503 or 504. Above roughly 1% under expected load is a problem.
Throughput
Requests per second the site handled. Watch whether it keeps rising as you add users. When it flattens while response times climb, you have hit a limit.
Server resources
While the test runs, watch CPU, memory and the database on the server. On a VPS, htop shows CPU and memory live. On shared or managed hosting, use the resource graphs in the control panel. The resource that hits 100% first is your bottleneck.
How many virtual users do you need?
Virtual users are not the same as visitors per day. A visitor reads a page for a while before clicking again, so a few dozen concurrent users can represent a lot of real traffic.
A rough way to estimate your peak concurrent users:
- Find your busiest hour in analytics. Say it had 1,200 sessions.
- Find the average session length. Say 2 minutes.
- Concurrent users is roughly sessions per hour multiplied by session minutes, divided by 60: 1,200 x 2 / 60 = 40.
So a site with 1,200 sessions in its peak hour has around 40 people on it at once. Test to that level for a load test, and two to three times higher for a stress test, to leave headroom for a good day.
Running your first test with k6
k6 is a free, open-source load testing tool. You write the test as a short JavaScript file and run it from the command line.
Step 1: Install k6
On macOS with Homebrew:
brew install k6On Windows with winget:
winget install k6 --source wingetOn Ubuntu and Debian, follow the repository instructions in the k6 documentation, then sudo apt install k6. Check it works:
k6 versionStep 2: Write a test script
Save this as load-test.js:
import http from "k6/http";
import { check, sleep } from "k6";
export const options = {
stages: [
{ duration: "1m", target: 10 },
{ duration: "3m", target: 40 },
{ duration: "1m", target: 0 },
],
thresholds: {
http_req_duration: ["p(95)<800"],
http_req_failed: ["rate<0.01"],
},
};
const pages = [
"https://staging.example.com/",
"https://staging.example.com/services",
"https://staging.example.com/blog/hosting-tips",
];
export default function () {
const url = pages[Math.floor(Math.random() * pages.length)];
const res = http.get(url);
check(res, { "status is 200": (r) => r.status === 200 });
sleep(Math.random() * 3 + 2);
}What it does:
- Stages ramp up to 10 virtual users over a minute, then to 40 over three minutes, then back down to zero.
- Thresholds mark the test as failed if the p95 response time exceeds 800 milliseconds or more than 1% of requests fail.
- The default function is what each virtual user does repeatedly: load one of your pages at random, check it returned 200, then pause for 2 to 5 seconds like a real reader.
Use a mix of real pages from your site, including at least one that cannot be served from cache, such as a search results page.
Step 3: Run a smoke test first
Override the stages to run 2 users for 30 seconds:
k6 run --vus 2 --duration 30s load-test.jsIf this shows errors, fix the script or the site before going further.
Step 4: Run the load test
k6 run load-test.jsk6 prints progress as it runs and a summary at the end.
Step 5: Read the summary
The summary includes lines like these. The values here are illustrative:
http_req_duration.......: avg=412ms min=96ms med=318ms max=3.1s p(90)=702ms p(95)=944ms
http_req_failed.........: 0.42% ✓ 21 ✗ 4979
http_reqs...............: 5000 16.6/sHow to read them:
- p(95)=944ms is above the 800 ms threshold, so the test fails that check. One request in twenty took nearly a second or longer.
- http_req_failed 0.42% is within the 1% limit.
- max=3.1s shows the worst case. Investigate whether slow requests cluster on one page.
Compare the timeline with your server's resource graphs. If response times rose as CPU reached 100%, the server needs more CPU or less work per request.
What to do with the results
| What you see | Likely bottleneck | Usual fix |
|---|---|---|
| CPU at 100%, response times climbing | Pages built from scratch on every request | Turn on page caching |
| Memory full, swap in use | Too many PHP workers for the memory, or a heavy database | Reduce workers, add memory, add an object cache |
| Database CPU high, slow queries in logs | Unindexed or heavy queries | Find slow queries, add indexes, remove heavy plugins |
| 502 or 504 errors appear suddenly | PHP-FPM or app server out of workers | Raise worker limits within your memory, add caching |
| Fine on cached pages, slow on search and cart | Uncached dynamic pages | Object cache, faster queries, larger server |
| Errors at a fixed number of users on shared hosting | Plan's resource limits | Upgrade the plan or move to a VPS |
The cheapest fix is almost always caching. A page served from cache uses a tiny fraction of the server work of a page built for each visitor. Run the test again after each change, so you know what helped. Why Is My WordPress Site Slow? lists the caching options, and Shared vs VPS vs Cloud Hosting covers when an upgrade makes sense.
Rules for safe load testing
- Only test what you own, or have written permission to test. Load testing someone else's site is indistinguishable from an attack.
- Read your host's acceptable use policy. Many shared hosts forbid load testing on their servers, because your test affects other customers. Ask support before testing, or test on a VPS or staging environment you control.
- Test a staging copy where possible, on the same kind of server as production. How to Create a WordPress Staging Site explains how. Staging should not send emails or take payments during the test.
- Start small and ramp up. Do not jump straight to hundreds of users.
- Exclude third parties. Do not include analytics, payment providers or external APIs in your test. You would be load testing their servers too.
- Pick a quiet time if you must test production, and tell anyone who might see alerts.
- Watch the server throughout, and stop the test with Ctrl+C if something goes wrong.
- Remember the CDN. If your site is behind a CDN, most requests may be answered by the CDN, not your server. That is realistic for visitors, but it may not stress your origin. Include uncached pages to test the server itself. What Is a CDN? explains the layers.
A load testing routine
| When | Test |
|---|---|
| After launching or moving hosts | Smoke test, then a load test to your expected peak |
| Before a big promotion or launch | Spike test to two or three times the expected rush |
| After major plugin, theme or code changes | Repeat the load test and compare with the last results |
| Every few months | Load test to confirm nothing has slowly degraded |
Keep the results of each run, including the date, settings and summary. Comparing runs over time is where load testing becomes most useful. A p95 that has crept from 400 to 900 milliseconds over six months tells you something changed long before visitors complain.
Frequently asked questions
What is website load testing?
Load testing sends simulated traffic from many virtual users to a website at once to measure how response times and error rates change as load increases. It shows whether your hosting and configuration can handle busy periods and where the bottleneck is.
How many users should I load test with?
Estimate peak concurrent users from analytics: sessions in your busiest hour multiplied by average session length in minutes, divided by 60. A site with 1,200 sessions in its peak hour and 2-minute sessions has about 40 concurrent users. Test to that level, then two to three times higher.
Is k6 free?
Yes. k6 is an open-source load testing tool you can install and run locally for free. You write tests as JavaScript files and run them from the command line. Grafana also offers a paid cloud service for running larger tests from multiple regions.
Can I load test my site on shared hosting?
Check with your host first. Many shared hosting providers prohibit load testing because the extra traffic affects other customers on the same server. Ask support, or test a copy of your site on a VPS or staging environment you control.
What is a good response time under load?
A useful target for content pages is a 95th percentile response time under about 800 milliseconds, in line with Google's 0.8-second guidance for Time to First Byte, with an error rate below 1%. Stores and apps may set different targets for checkout and search pages.
What is the difference between a load test and a stress test?
A load test checks performance at your expected normal peak. A stress test keeps increasing traffic beyond that point to find where the site breaks and how it fails, so you know how much headroom you have.
What usually fixes a site that fails a load test?
Page caching fixes most failures on content sites, because cached pages need far less server work. Other common fixes are an object cache for dynamic pages, faster database queries, tuning PHP worker limits, and upgrading to more CPU or memory if needed.
Sources
Update history
- First published.