WordPress
Slow WordPress site: a technical analysis beyond the usual advice
Why a WordPress site is really slow: TTFB, autoload, queries, hooks, page builders and third parties. A developer's diagnosis, and when caching is no longer enough.
Fabio Folgori5 min read

The same advice on "slow WordPress site" has been around for years: compress images, install a cache, remove a few plugins. It is correct advice, but it stays on the surface. When a WordPress site is structurally slow, the reason almost always lies in how it generates pages and how much work it pushes onto the browser. This is the diagnosis I run, in the order I run it.
Two different problems: server and browser
Slowness has two sources that must be separated straight away.
- Server side: the time PHP and the database take to produce the HTML. It shows in the TTFB of uncached pages and affects LCP.
- Browser side: how much JavaScript and CSS the page has to download, parse and execute. It affects LCP and above all INP.
Mixing them up leads to the wrong fixes: more powerful hosting does not fix an INP ruined by a builder, and an asset optimiser does not fix 800 milliseconds of queries.
Server side: what WordPress does on every request
On every request not served from cache, WordPress loads core, the theme and all active plugins, even those that do nothing on that page. Then it runs the hook chain, reads options and fires the template's queries. Time almost always piles up in the same places.
Autoloaded options
Every option saved with autoload = yes in wp_options is read on every request. Badly uninstalled plugins, transients that never expire and serialised settings hundreds of kilobytes long end up there. I have seen sites with several megabytes of autoload: memory and time paid on every single page. You measure it with a query summing LENGTH(option_value) and clean it up carefully, not with a "database cleaner" plugin run blindly.
Queries and meta
WP_Query with a meta_query on several keys, ordering by custom fields, LIKE searches on post_content: on wp_postmeta tables with millions of rows they get slow because those fields are not usefully indexed. The real fixes are a better data model (taxonomies where appropriate, dedicated tables for structured data) and a persistent object cache such as Redis so the same queries are not repeated.
Heavy hooks and external calls
A plugin that calls a remote API, checks a licence or regenerates something on init blocks page generation until the response arrives. Query Monitor shows the HTTP requests made during the page: there should be none.
WP-Cron
By default WP-Cron runs during visits. On sites with many scheduled events, the unlucky visitor pays for the jobs. It should be disabled and replaced with a system cron.
Browser side: where INP is lost
The main culprit here is almost always the page builder. It generates deep, redundant DOM, loads libraries for animations, sliders and widgets on every page, and adds JavaScript that runs at startup. The result is long tasks on the main thread and interactions that respond late.
The other usual suspects:
- third-party scripts: tag managers with ten tags, chat, maps, pixels, heavy cookie banners. Each competes for the main thread;
- unused global CSS: hundreds of kilobytes of rules for components that do not exist on the page;
- fonts: too many variants, loaded without a suitable
font-displayor from external servers.
"Optimising" here often means adding another plugin that defers, combines or delays scripts. It works up to a point, and meanwhile adds one more layer that can break with every update.
The diagnostic method
- Real data first: Search Console Core Web Vitals (CrUX data) tell you which groups of pages have problems and on which metric. A single lab test is not enough.
- Uncached TTFB, measured on the home page, an archive and a single post.
- Query Monitor on those pages: number and duration of queries, slowest components, HTTP requests, autoload size.
- Browser Performance panel with CPU throttling: long tasks, most expensive scripts, the LCP element and its source.
- Component inventory: for each plugin, what it loads and where. Often half the plugins can be removed or replaced with a few lines of code.
Only after this phase does it make sense to act. Detail on the metrics is in Core Web Vitals explained by a developer.
When caching becomes a patch
Page caching is essential on WordPress, but it should be seen for what it is: a way of not running WordPress. If the site is fast only when the cache is warm, the problem is still there: logged-in users pay for it, as do the cart, search, bots requesting uncached pages and every purge after an update.
When I notice that optimisation consists of stacking layers (page cache, object cache, asset optimiser, CDN, a plugin delaying scripts) to compensate for a theme and a plugin set that cannot be touched, that is the sign the problem is architectural.
My take
I love WordPress and I know how to make it fast: on hand-written projects, with a custom theme and few plugins, the results are excellent. But most of the slow sites I receive are not slow because of one isolated mistake: they are slow because they grew by accumulation, with components so tightly bound that removing one is a risk. In those cases I prefer to be honest: it can be optimised, but rethinking the site often costs less.
If the site does not need content generated on every request, generating it once and serving it from a CDN removes half the problems in this article at the root. That is why I am moving many projects to Nuxt and Netlify.
Why work with me
I have been programming since 1999, delivered more than 300 projects and work as an external developer with about 30 agencies, from Rome and remotely. I run the diagnosis with a developer's tools, not a score, and tell you whether it pays to optimise or to change course.
If your WordPress site is slow, get in touch: in a call of about 20 minutes we look at the real data and find where the time goes. The service is in Speed and SEO.
Frequently asked questions
Page caching hides generation time for anonymous visitors but does not remove it: logged-in users, the cart, search and uncached pages stay slow. And it does nothing for the work done in the browser, which is where INP is lost.
Only if the server is the bottleneck. You find out by measuring TTFB on uncached pages and profiling requests: if PHP takes 1.5 seconds because of queries and hooks, a more powerful server only helps partially.
Query Monitor for queries, hooks and HTTP requests on the server; Search Console CrUX data for real user experience; the browser Performance panel for long tasks. On important projects, a profiler such as Xdebug or an APM.
When every improvement needs one more plugin, when the theme or builder is the bottleneck and cannot be removed, or when the site does not need dynamic content. Then static generation is often cheaper than endless optimisation.
- #wordpress
- #site speed
- #performance
- #core web vitals
- #database


