The standard response to a slow WordPress site is to install a caching plugin. Sometimes it helps considerably. Often it produces a modest improvement that masks the real problem for another year, until the site is slow again and there is now a caching layer complicating every diagnosis.
Slowness has causes, and they are findable. Here is how to find yours, in roughly the order that causes tend to occur.
First, measure the right thing
Before changing anything, establish what “slow” means for your site. Two measurements matter and they are not the same.
Lab measurements come from tools that load your page under controlled conditions. They are repeatable and useful for comparing before and after a change. They are also artificial — a specific device, a specific connection, no real user behaviour.
Field measurements come from real visitors on real devices. They are what actually matters, because they reflect the phone on a train rather than a data-centre connection. Core Web Vitals are field metrics: Largest Contentful Paint at or under 2.5 seconds, Interaction to Next Paint at or under 200 milliseconds, and Cumulative Layout Shift at or under 0.1, each measured at the 75th percentile of your real visitors.
Use lab tools to diagnose and compare. Use field data to decide whether you actually have a problem. A site with an unimpressive lab score and healthy field data is usually fine; the reverse is not.
Separate server time from browser time
This single distinction narrows the search enormously.
Time to first byte tells you how long the server took to produce the page. If that is high — say, over half a second consistently — the problem is on the server: hosting, PHP, or the database. No amount of image optimisation will help.
If time to first byte is fine but the page still feels slow, the problem is in the browser: images, fonts, scripts, or layout that shifts as things load. No amount of server tuning will help.
Getting this wrong is why so much performance work disappoints. Optimising the half you are not slow in produces exactly the improvement you would expect: none.
Server-side cause one: the hosting
Cheap shared hosting is slow in ways that are difficult to work around, because you are competing for resources with hundreds of other sites and have no visibility into what they are doing. If your time to first byte varies wildly between requests for the same cached page, that variance is usually the neighbours.
Also check the PHP version. Sites running several major versions behind are leaving significant performance on the table, quite apart from the security implications of running unsupported software. Upgrading PHP is frequently the single highest-value change available and is often free.
Server-side cause two: the database
This is where most genuinely slow WordPress sites are slow, and it is the least commonly investigated.
Enable query profiling and look at what runs on your slowest page. What you are looking for is a small number of queries taking a disproportionate share of the time, queries running without an index, or the classic pattern where a query runs once per item in a loop — twenty products producing sixty-one queries.
The usual culprits: meta queries filtering on postmeta without appropriate indexing, plugins that query on every page load regardless of whether their output is used, and tables that have grown far beyond their original size. A postmeta table with several million rows behaves very differently from one with fifty thousand.
Also look at what is simply accumulating. Post revisions with no limit, expired transients that never got cleared, log tables from plugins removed years ago, and orphaned metadata. None of it is a fault; all of it costs time on every query that touches those tables.
Object caching helps considerably here, and it is different from page caching. Page caching stores the finished HTML. Object caching stores the results of database queries so they are not repeated, which benefits logged-in users and dynamic pages that page caching cannot help at all. For a WooCommerce store, object caching is frequently the highest-impact change available.
Server-side cause three: too much PHP
Every active plugin runs code on every page load, whether or not its functionality appears on that page. A plugin providing a contact form typically loads its code on every page of the site, not only the contact page.
Thirty plugins is not automatically a problem, and five badly written ones can be worse than thirty good ones. But the correlation is real, and the fix is genuinely to audit them: what does each one do, is that functionality still used, is there overlap, and is it maintained. Sites we inherit are typically carrying several plugins nobody can account for.
Browser-side cause one: images
Images are the largest part of most pages, and image problems are the easiest to fix.
Check for images served far larger than they display — a 3000-pixel-wide photograph rendered in a 400-pixel column is downloading roughly fifty times more data than it needs. Check that images specify width and height attributes, because without them the browser cannot reserve space and the page jumps as each one arrives, which is what Cumulative Layout Shift measures. Check that below-the-fold images are lazy-loaded and that above-the-fold ones are not, since lazy-loading your hero image actively delays the metric you most want to improve.
Modern formats help, but correct sizing helps more. A properly sized JPEG beats an oversized WebP comfortably.
Browser-side cause two: scripts and fonts
Third-party scripts are the most common cause of a site that measures well in a lab and performs badly for real users. Analytics, tag managers, chat widgets, heat mapping, advertising pixels and embedded media each add requests to servers you do not control, and any one of them having a slow day makes your site slow.
Audit them the way you audit plugins: what is it, who asked for it, is anyone reading the data, and what does it cost. Sites routinely carry tracking scripts for tools nobody has logged into for two years.
Web fonts are the other common offender. Each font file is a render-blocking download, and a site loading four weights of two families is downloading a great deal for a typographic distinction most visitors will not notice. Using system fonts eliminates the cost entirely; if a brand font is genuinely required, self-host it, subset it, preload it, and limit the number of weights.
Where caching plugins actually fit
Page caching is genuinely valuable. It removes PHP and database work for anonymous visitors, which for a content site is most of the traffic. It should be enabled on essentially every WordPress site.
What it does not do is fix a slow site. It hides slowness for cached requests while leaving it intact for everything else: logged-in users, cart and checkout pages, search results, forms, and the first visitor to any page after a cache clear. A store whose product pages take four seconds to build will still take four seconds for every customer with something in their basket.
So the order matters. Fix the underlying causes first, then add caching on top of a site that is already reasonably fast. Adding caching to a slow site produces a site that is fast for some visitors and slow for the ones who are actually buying from you.
A practical order of work
If you are starting from scratch on a slow site, this sequence finds the most improvement for the least effort:
- Get field data. Confirm you have a real problem and where it is.
- Check time to first byte. Decide whether this is a server or a browser problem.
- Upgrade PHP if it is behind. Often free, often significant.
- Profile the database on your slowest page. Fix the worst queries.
- Add object caching, particularly for a store or a site with logged-in users.
- Audit plugins and third-party scripts. Remove what nobody uses.
- Fix image sizing, dimensions and loading priority.
- Reduce or eliminate web fonts.
- Add page caching on top of the now-faster site.
- Re-measure field data after four weeks and confirm it moved.
The last step is the one most often skipped, and it is the only one that tells you whether any of the previous nine were worth doing.