How to load test your WordPress site without lying to yourself
The method for a fair WordPress load test: replay a realistic traffic mix, test cached and uncached paths separately, ramp instead of flooding, repeat the runs, and read error rates and percentiles before averages. With what each family of tool is good for, and how to interpret what the numbers say.

By Sam Moreton
First-hand + researched
A fair load test of a WordPress site does five things. It replays a realistic mix of pages and actions instead of hammering one URL. It tests the cached and uncached paths separately, because they are two different systems wearing one domain name. It ramps the load up in stages instead of dumping it all at once. It repeats the runs and reports the spread between them. And it covers the database-backed paths, admin, search, cart, where the expensive work and the revenue live. Do those five and you learn where your site actually bends. Skip them and you learn how fast a cache can print a file, which needed no test.
Write a scenario before you open a tool
The first act of self-deception in load testing is pointing a tool at the homepage and letting it rip. Visitors do not all request one URL: they land on posts from search, browse categories, run searches, and a share of them log in, add to cart, check out. Weight the test the way your access log says the week actually looks, and put it in a scenario file the tool can replay: k6 scripts in JavaScript, Locust in Python, JMeter in its own format. The scenario is the part of the test that is yours; the tool is interchangeable.
Cached and uncached are two tests
A page-cached WordPress site runs two workloads under one domain: near-static HTML from cache, and full PHP plus database work for everything the cache excludes. Test them separately and label them. Force the uncached path with a cache-busting query parameter or a URL excluded from caching, and remember that admin, search, and cart pages are uncached by nature. Reporting only the cached number flatters every host on the chart; the uncached path is where servers actually differ.
Ramp, watch, note
Increase the load in stages and watch for two thresholds: where response times start climbing, and where errors begin. Those two points, and the gap between them, are the finding. A flood from the first second mostly finds the cache's breaking point and skips the interesting middle, where the site goes from fine to sluggish to failing. Ramping walks you through that middle.
Repeat, and admit the spread
Run the same scenario several times, ideally across different hours, and report the median alongside the spread. One run is one sample, and the sample of the moment is noise with confidence. If run-to-run results disagree wildly, the instability is itself a finding: something on the server, a backup job, a cron burst, a noisy neighbour, is competing with your traffic.
Test the paths that cost money
The homepage survives almost anything behind a cache. The checkout does sessions, database writes, and usually email, all uncached, and it is where the revenue lives. Include admin page loads while public traffic runs, because admin screens that crawl under load are the complaint that public-page-only tests never predict, and include search, which hits the database directly on most setups. If you run WooCommerce, time the add-to-cart and checkout requests specifically.
The tools, by family
Scriptable generators you run yourself: k6 for scripted scenarios with ramping and percentile output, Locust if you would rather write Python, JMeter if your organisation already has test plans, and wrk or hey for quick single-URL checks where scenario fidelity does not matter. Managed services, k6 Cloud, BlazeMeter, Loader.io and the rest, run from their own infrastructure in many regions; they suit teams with no clean machine to generate from, and the vantage point is theirs, which is fine as long as you say so in the notes. WordPress plugins that self-test are the third family: convenient, and mostly indicative, because they generate load from your own server or scheduler, skipping the network path real visitors take. Good as a smoke test, wrong as a comparison.
Two cautions apply to all of them. Check the machine doing the generating: if its CPU is maxed during the run, you measured the generator. And check your host's terms before testing production, especially on shared hosting, where your test lands on your neighbours too.
Reading the output
Error rate before throughput. Any run with errors in it is not a throughput result; note the load at which errors start, fix or size around that point, and run again. A requests-per-second figure earned while the site returned errors is a failure rate with better marketing.
Percentiles before averages. The average summarises a distribution while hiding its tail, and the tail is your worst visitors. Read the median for the typical experience, then the ninety-fifth and ninety-ninth percentiles for what the unlucky get, and decide which one you are optimising for. Splitting time to first byte from full download tells you whether the server or the page weight is doing the work; the TTFB guide covers that distinction.
A fair test tonight
Clone the site to staging first, because load testing production makes you the outage. Pick your top URLs by real traffic, plus one uncached path. Write the ramp as a scenario or a tool configuration, run it three times, and record the environment with the results: server plan, region, plugin count, cache states, generator, time of day. Compare before and after any change by re-running the same scenario unchanged, which is the only comparison that means anything. The multi-host version of this method, the one we hold ourselves to before publishing hosting comparisons, is written out in the throughput benchmark playbook.