To speed up a WordPress site, measure first, then fix things in order of impact: server response time (hosting, PHP version, page and object caching), then images, then plugins, then render-blocking CSS, JavaScript and fonts. Most slow WordPress sites I look at are not slow for one dramatic reason. They are slow because of five ordinary ones stacked together. This guide walks through each, with the settings I actually use, and shows how each one maps onto the Core Web Vitals Google measures: LCP, INP and CLS.
Before you speed up a WordPress site: field vs lab data
Run your URL through PageSpeed Insights and look at the top section first. That is field data from the Chrome UX Report (CrUX): real Chrome users on real devices, over the previous 28 days. It is what Google uses for its page experience signals. The big score below it is lab data from a single simulated Lighthouse run on a throttled mobile device. The lab run is useful for diagnosing problems, but it is not what your visitors experience.
| Metric | Measures | Good | Poor |
|---|---|---|---|
| LCP (Largest Contentful Paint) | When the main content appears | ≤ 2.5 s | > 4.0 s |
| INP (Interaction to Next Paint) | How fast the page responds to taps and clicks | ≤ 200 ms | > 500 ms |
| CLS (Cumulative Layout Shift) | How much the layout jumps around | ≤ 0.1 | > 0.25 |
| TTFB (Time to First Byte) | Server response time (diagnostic) | ≤ 0.8 s | > 1.8 s |
A page passes when the 75th percentile of visits is in the "good" range. INP replaced First Input Delay as a Core Web Vital in March 2024, and it is the metric WordPress sites most often fail now. If your site does not have enough traffic for field data, use the lab numbers and Chrome DevTools, but test on a throttled mobile profile, not your fast desktop.
Write down the numbers for your homepage, a typical post or product page and, for WooCommerce, the cart. You need a baseline to know whether anything you change actually helps.
Hosting and PHP version: fix TTFB first
If TTFB is over a second, nothing on the front end will rescue your LCP. The server is the first thing I check. Three things matter most.
- PHP version. Each major PHP release has been measurably faster than the last, and at the time of writing PHP 8.1 and everything older no longer receive security fixes. I move sites to PHP 8.3 or newer, after checking plugin compatibility on staging. Check yours under Tools → Site Health → Info → Server.
- OPcache enabled with enough memory, so PHP is not recompiling files on every request.
- Enough PHP workers. On cheap shared hosting, a handful of simultaneous uncached requests queue up and everyone waits. WooCommerce, membership sites and anything with logged-in users need more.
php -v
php -i | grep -E 'opcache.enable |opcache.memory_consumption'Page cache and object cache
WordPress builds every page with PHP and a few dozen database queries. A page cache stores the finished HTML so most visitors get it in milliseconds without touching PHP. This single change usually does more for TTFB than anything else.
- Server-level cache (Nginx FastCGI cache, Varnish, or LiteSpeed Cache on a LiteSpeed server) is the fastest option when your host supports it.
- A caching plugin such as WP Super Cache or W3 Total Cache works everywhere.
- Edge caching with Cloudflare APO, or a Cache Rule that bypasses on WordPress login and WooCommerce cookies, serves HTML from Cloudflare's network close to the visitor. That helps a lot when your audience is spread across continents.
Use one page cache, not three layered together, and make sure cart, checkout and account pages are excluded. Edge caching WordPress HTML safely is a big part of my Cloudflare setup work, because getting the bypass rules wrong shows one customer's cart to another.
A persistent object cache (Redis or Memcached) is different: it caches database query results between requests, which speeds up exactly the traffic page caching cannot help, meaning logged-in users, the admin area and WooCommerce. With Redis installed on the server, the Redis Object Cache plugin and two lines in wp-config.php are enough:
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_CACHE_KEY_SALT', 'example.com:' );Improve LCP in WordPress: images
On most pages, the LCP element is an image, usually the hero or featured image. Once the server is fast, images are the next biggest lever.
- Use modern formats. WordPress core supports uploading WebP since 5.8 and AVIF since 6.5, provided the server's image library supports them. Both are typically much smaller than JPEG at similar quality.
- Serve the right size. WordPress generates multiple sizes and a
srcsetautomatically. That only works if themes use them; a 2,400px original squeezed into a 400px column is still common. - Do not lazy-load the LCP image. Since WordPress 6.3, core tries to skip lazy-loading on the first large image and adds
fetchpriority="high". Page builders and sliders often defeat that, so check the actual HTML. - Set width and height on every image so the browser reserves space. That is the most common CLS fix.
In the lab report, the "Largest Contentful Paint element" diagnostic tells you exactly which element it is. If it is a background image set in CSS, the browser discovers it late; a regular <img> or a preload hint fixes that.
Audit plugins with Query Monitor
"Too many plugins" is the wrong way to think about it. One badly written plugin does more damage than twenty good ones. Install the free Query Monitor plugin, load a slow page while logged in, and look at:
- Queries by Component — which plugin runs the most, and the slowest, database queries.
- HTTP API Calls — plugins calling external APIs on every page load, which is a classic cause of a slow WordPress site that no cache fully hides.
- Scripts and Styles — assets loaded on pages that do not need them, such as a form plugin loading everywhere.
Also check the autoloaded options, which WordPress loads on every single request. Plugins that were deleted years ago often leave large autoloaded data behind:
wp db query "SELECT option_name, LENGTH(option_value) AS bytes FROM wp_options
WHERE autoload IN ('yes','on','auto-on','auto') ORDER BY bytes DESC LIMIT 15;"Anything over a few hundred kilobytes in total is worth investigating. Remove what you do not use; where a plugin is genuinely broken rather than just heavy, that is a fix I handle under WordPress bug fixing.
Render-blocking CSS, JavaScript and fonts
Every stylesheet and synchronous script in the <head> must download before the browser can show anything. The fixes, in order of safety:
- Defer non-critical JavaScript with
defer, or delay it until user interaction for things like chat widgets and heatmaps. - Stop loading assets where they are not used, using the Query Monitor findings above.
- Inline critical CSS and load the rest asynchronously. This helps LCP a lot, but it breaks layouts easily, so test on staging.
Fonts are a common hidden cost. Self-host them rather than loading from a third-party domain, use WOFF2 only, limit yourself to the weights you actually use, set font-display: swap, and preload the one font used above the fold.
Fix INP: JavaScript on the main thread
INP measures how long the page takes to respond visually after a click or tap. Poor INP on WordPress almost always means too much JavaScript competing for the main thread: page builder scripts, sliders, analytics and ad tags, consent banners, chat widgets. Record an interaction in the Chrome DevTools Performance panel and look for long tasks over 50 ms. Then remove or delay the scripts responsible. Third-party tags are the usual offenders, and loading them only after interaction is often the difference between failing and passing.
That is the whole method: measure, fix the server, cache, then images, plugins and front-end weight, re-measuring after each step. Field data takes up to 28 days to reflect changes, so be patient. If you want it done for you, my WordPress speed optimization service works through exactly this list against your real Core Web Vitals, at $20/hour for small fixes or a fixed price agreed in writing for a full WordPress performance overhaul. If the problem turns out to be the origin timing out behind Cloudflare, see my guide to fixing Cloudflare 522 errors.
Frequently asked questions
Why is my WordPress site slow only in the admin area?
The dashboard is never page-cached, so it exposes slow database queries, heavy plugins and external API calls that caching hides on the front end. Install Query Monitor and load the slow admin screen: it shows which plugin is responsible. A large autoloaded options table and WooCommerce admin reports are common culprits.
Is a caching plugin enough to speed up WordPress?
It usually fixes server response time for anonymous visitors, which is a big win. It does nothing for oversized images, heavy JavaScript, logged-in users or WooCommerce carts and checkouts. Caching is the first step, not the whole job.
Does a page builder make WordPress slow?
Page builders add extra markup, CSS and JavaScript to every page, which tends to hurt LCP and INP. A well-configured site can still pass Core Web Vitals with one, but it takes more work. Stacking several builder add-on packs is where performance usually falls apart.
Why does my PageSpeed score change every time I test?
The lab score is a single simulated run, affected by server response time, third-party scripts and network variation on Google's side. Swings of a few points are normal. Judge progress by the field data at the top of the report, which reflects 28 days of real visits.