Book me

To speed up WordPress, fix it in the order the browser experiences it. Start with the server response: a supported PHP version with OPcache, a page cache that actually serves HTML, and a persistent object cache for the requests that can’t be cached. Then clean the database, especially autoloaded options and slow queries. Only after that work on the front end: the LCP image, render-blocking CSS, plugin and third-party JavaScript, fonts and layout shifts. Measure every step with field data from real visitors, not a single lab score. Most slow sites I audit need fewer plugins and better architecture, not another optimization plugin.

That is the short version. The rest of this guide is the long one: the order I follow in audits, what each layer costs you, how to tell which layer is your problem, and where to go deeper. If you want the reasoning behind the order first, read why your WordPress site is slow for structural reasons. If you already know the site is slow and need to find the cause, start with how to find out why your WordPress site is slow.

What does “fast” mean for a WordPress site?

Fast has a definition, and it is Google’s Core Web Vitals measured on real visitors. Google takes the 75th percentile of page loads over a rolling 28-day window from the Chrome UX Report (CrUX). A page passes when all three metrics are good at that percentile.

MetricWhat it measuresGoodPoor
————
LCP (Largest Contentful Paint)When the main content appears≤ 2.5 s> 4 s
INP (Interaction to Next Paint)How quickly the page responds to clicks, taps and keys≤ 200 ms> 500 ms
CLS (Cumulative Layout Shift)How much the layout jumps around≤ 0.1> 0.25
TTFB (Time to First Byte), diagnostic onlyWhen the first byte of HTML arrives≤ 0.8 s> 1.8 s

INP replaced FID as the responsiveness metric in March 2024. TTFB is not a Core Web Vital, but I put it in the table on purpose. On WordPress it is usually where the trouble begins, because nothing renders until the HTML arrives. I cover all of this in more depth in Core Web Vitals for WordPress: the complete guide.

The other half of the definition is that “fast” means fast for your visitors, on their phones and networks. A Lighthouse score of 98 on your laptop does not tell you that. The difference between the two kinds of data is the most common source of confusion I see, so it has its own article: field data vs lab data.

Where should you start to speed up WordPress?

Start by measuring, and measure per template, not per site. A WordPress site is a handful of templates: home, page, post, archive, search, and on a store the product, category, cart and checkout. Each one has a different LCP element, different plugins running and different cache behavior. Averaging them hides the one that fails.

This is the short measuring routine I run before I change anything:

  1. Open the Core Web Vitals report in Google Search Console and note which URL groups fail and on which metric.
  2. Run one representative URL per template through PageSpeed Insights and read the field data block at the top before the lab score.
  3. Check TTFB on a cached and an uncached request for each template. A logged-in request or a URL with a query string usually skips the cache.
  4. Install Query Monitor on a staging copy and look at the slowest templates: query count, slow queries, HTTP API calls and which plugin owns them.
  5. Write down the baseline. Without it you can’t prove anything later.

The diagnostic side gets its own walkthrough in why is my WordPress site slow, and the tools are compared in Core Web Vitals tools. If you prefer a list to tick off, use the WordPress speed optimization checklist.

What order should you fix things in?

From the bottom of the stack up. Each layer sets a floor for the layers above it. If the server takes 1.5 seconds to send HTML, the best image optimization in the world still leaves you 1 second to render the LCP element before you miss 2.5 seconds. So I fix the floor first.

LayerTypical symptomFirst fixGo deeper
————
Hosting and PHPHigh TTFB even on simple pagesSupported PHP version, OPcache, enough PHP workersPHP-FPM and OPcache tuning
Page cacheTTFB fine on some visits, slow on othersCache that serves HTML without booting PHP, fewer bypass rulesbest WordPress caching plugin
Object cacheSlow admin, cart, account and search pagesRedis or Memcached through an object cache drop-inRedis object cache for WordPress
DatabaseSlow everything, worse over timeTrim autoloaded options, fix slow queriesWordPress database optimization
Front endGood TTFB, poor LCP, INP or CLSLCP image priority, less CSS and JavaScriptLCP, INP, CLS
Third partiesPoor INP, long main-thread tasksRemove, delay or replace tagsINP in WordPress

This order also saves money. Server fixes help every template at once. A front-end fix usually helps one template, and sometimes only one element on it.

Does hosting really matter for WordPress speed?

Yes, and it sets the limit for everything else. People ask me for the best WordPress hosting for speed, and I don’t answer with a brand. I answer with a list of things to check, because the same company can sell you a fast plan and a slow one.

When I evaluate a host for a WordPress project I look at:

  • PHP versions that are still supported upstream, and how easy it is to switch between them
  • OPcache enabled with enough memory for the size of the codebase
  • how many PHP workers the plan allows and what happens to requests when they are all busy
  • a server-level page cache (Nginx FastCGI cache, LiteSpeed cache, Varnish or an equivalent), or at least support for one
  • Redis or Memcached available for a persistent object cache
  • a data center close to most of your visitors, or a CDN that can cache HTML at the edge
  • whether you share CPU and database with other customers, and how that shows up under load
  • access to logs, the PHP slow log and ideally an APM tool, so you can see where time goes

Shared hosting can be fine for a brochure site with a good page cache. It stops being fine when most of your traffic is uncached: WooCommerce carts, membership areas, LMS dashboards, search. Those requests run PHP and the database every time, so worker count and CPU become the real limit. The server side is covered in detail in TTFB in WordPress and in PHP-FPM and OPcache tuning for WordPress.

How should you set up caching in WordPress?

Think of caching as three separate layers that solve different problems. Mixing them up is how people end up with three caching plugins and a site that is still slow.

  • A page cache stores the finished HTML of a page and serves it to the next anonymous visitor without running WordPress. This is the biggest TTFB win for content sites.
  • An object cache stores the results of database queries and computed values between requests. WordPress has an object cache built in, but by default it only lives for one request. A persistent backend such as Redis keeps it across requests, which helps the pages a page cache can’t serve: logged-in users, carts, checkouts, the admin.
  • An edge cache, usually a CDN, keeps copies of static files and sometimes of HTML in locations near your visitors. It cuts network distance, which no server tuning can do.

I explain how the three fit together, and which ones a given site needs, in page cache, object cache, edge cache: which one you actually need. Setting up the object cache layer with Redis is covered step by step in Redis object cache for WordPress.

Which caching plugin should you use?

The one that matches your server. If the host runs LiteSpeed, LiteSpeed Cache talks directly to the server cache. On Nginx or Apache stacks, a plugin that writes static HTML files or a host-level cache does the job. What I compare is architecture: where the cache lives, how purging works, what it does to CSS and JavaScript, and how it handles logged-in users and WooCommerce. The long comparison is in best WordPress caching plugins, and the head-to-head posts are WP Rocket vs LiteSpeed Cache, FlyingPress vs WP Rocket and NitroPack vs WP Rocket.

Why is the page cache not working?

In audits, the usual reason the page cache “doesn’t work” is that it isn’t being used. Check these before you blame the plugin:

  • cookies set for every visitor (consent tools, A/B testing, some analytics setups) that the cache treats as a reason to bypass
  • campaign query strings like utm_source producing a cache miss on every ad click
  • a very short cache lifetime, or a purge that clears everything on every post update
  • a plugin that starts a PHP session on every page
  • two caching layers fighting each other, for example a plugin cache behind a host cache with different rules

Read the response headers. Most caches add a header that says HIT or MISS. If your landing pages show MISS, that is the first fix. WordPress Site Health has also checked for a page cache since version 6.1, which is a quick way to spot an obvious gap.

How do you keep the database from slowing down every request?

WordPress stores most configuration in the wp_options table. Options marked as autoloaded are loaded on every request, cached or not, logged in or not. Plugins add to that list and many never remove their rows when they are uninstalled. Over the years the autoloaded data grows, and every uncached request pays for it. Since WordPress 6.6, Site Health warns when autoloaded options get too large.

What I usually find and fix:

  • autoloaded options left behind by plugins that were removed long ago
  • expired transients piling up in wp_options because nothing cleans them
  • huge wp_postmeta tables, often from page builders, revisions or WooCommerce on stores that never moved orders to HPOS
  • queries without a usable index, which show up in Query Monitor or the MySQL slow query log
  • WP-Cron running on visitor requests on a busy site, instead of a real system cron

None of this needs a “database cleaner” that deletes things blindly. It needs you to know which plugin owns which rows. The method, with WP-CLI commands, is in WordPress database optimization: wp_options autoload and beyond. If the slowness is mostly in wp-admin on a store, read how to fix a slow WooCommerce admin.

How do you fix front-end performance in WordPress?

Once the HTML arrives fast, the remaining work is what the browser has to download, parse and run. On WordPress that comes from three places: the theme, the plugins and third-party tags. I go through it by metric.

Images and the LCP element

On most WordPress pages the LCP element is an image: the hero, the featured image or the first product photo. Fix it like this:

  • make sure the LCP image is not lazy loaded (WordPress lazy loads images by default and usually skips the first one, but themes and builders can override that)
  • give it fetchpriority="high"; WordPress 6.3 started adding this to the image it judges most likely to be the LCP
  • serve a size that matches the slot, using the srcset WordPress already generates
  • use modern formats: WordPress supports WebP uploads since 5.8 and AVIF since 6.5
  • avoid hiding the hero behind a slider or a JavaScript animation that delays it

The full LCP method, including how to read its four sub-parts, is in LCP in WordPress: causes and fixes.

CSS and render blocking

Most themes and plugins load their stylesheets on every page, whether the page uses them or not. A contact form plugin’s CSS on the blog archive is a typical case. Options, from safest to riskiest: dequeue assets on templates that don’t need them, inline the critical CSS for above-the-fold content, and remove unused CSS with a tool. The last one is where I see the most breakage, so test it on every template and on logged-in states.

JavaScript and INP

INP is the metric WordPress sites fail most quietly, because lab tools barely see it. The causes are long tasks on the main thread: sliders, mega menus, builder widgets, chat widgets, tag managers, ad scripts. What helps:

  • load non-essential scripts with defer or async; WordPress 6.3 added loading strategies to wp_register_script and wp_enqueue_script
  • remove jQuery-dependent plugins that do something CSS can do
  • delay chat, video and social embeds until the visitor interacts
  • reduce DOM size, which mostly means simpler layouts and fewer nested builder containers

“Delay all JavaScript” settings in optimization plugins can move the cost to the first interaction, which is exactly what INP measures. Use them carefully and check INP in field data afterwards. More in INP in WordPress: fixing slow interactions.

Fonts

Self-host the fonts you use, load only the weights you need, preload the one used in the LCP text if there is one, and set font-display. The Font Library in WordPress 6.5 makes self-hosting easier on block themes. Swapping fonts can also move the layout, which brings us to CLS.

Layout shifts

CLS on WordPress usually comes from images and embeds without dimensions, ad slots and banners injected above content, cookie bars that push the page down, and late font swaps. The fix is to reserve space for everything that loads later. The full list is in CLS in WordPress: stop layout shifts.

What about third-party scripts?

They deserve their own section because they sit outside your code and outside your cache. Analytics, tag managers, heatmaps, chat, consent tools, ad networks, review widgets and pixels all run on the visitor’s main thread. In audits they are often the single largest source of poor INP on otherwise well-built sites.

My process is boring and it works. List every tag the site loads. For each one, ask who uses its data and when they last looked. Remove the ones nobody can defend. Load the rest after the page is usable where the vendor allows it, and keep the tag manager from becoming a place where anyone can add scripts without review. This is a governance problem as much as a technical one, which is why I also cover it in enterprise WordPress, where tag sprawl is the norm.

Is your page builder slowing down WordPress?

It can be, and the cost is mostly front-end: more DOM nodes, more CSS and more JavaScript per page than a block theme needs for the same layout. That shows up in LCP and INP. A builder site can still pass Core Web Vitals. It takes discipline: fewer nested containers, fewer widgets that load their own scripts, and using the builder’s own performance settings.

For a site already on Elementor, the practical steps are in how to speed up Elementor. If you are deciding what to build the next version on, read Elementor vs Gutenberg performance, which compares how each one produces markup and loads assets.

How is WooCommerce different?

A store has more pages that can’t be served from the page cache: cart, checkout, my account, and often the product pages for logged-in customers. That puts the load back on PHP and the database, so the server, object cache and database layers matter more on a store than on a blog.

The usual WooCommerce work includes:

  • a persistent object cache, because carts and sessions hit the database constantly
  • checking the cart fragments request, which can run on pages that don’t need it
  • High-Performance Order Storage (HPOS), which moves orders out of the posts and postmeta tables
  • product and category templates with many images and filters, which need the same LCP work as any other page
  • a separate look at wp-admin, where order lists, reports and extensions add their own queries

The front-end and server steps are in WooCommerce speed optimization, and the back office has its own post: fix a slow WooCommerce admin.

Which WordPress core features already help with speed?

Core has picked up a lot of performance work in recent releases, much of it from the WordPress Performance Team. Before you add a plugin for something, check that core doesn’t already do it.

FeatureSinceWhat it does
———
WebP uploads5.8Accepts and generates WebP images
Page cache check in Site Health6.1Flags when no page cache is detected
fetchpriority on images6.3Adds fetchpriority="high" to the likely LCP image
Script loading strategies6.3Lets themes and plugins register scripts with defer or async
AVIF uploads6.5Accepts AVIF images where the server supports it
Interactivity API6.5A standard way to add front-end interactivity to blocks
Font Library6.5Manages and self-hosts fonts in block themes
Autoload size check in Site Health6.6Warns when autoloaded options are too large
Speculative loading6.8Uses the Speculation Rules API to prefetch likely next pages

The Performance Lab plugin is where the Performance Team tests features before they reach core. It is a reasonable place to try new options on staging.

Which speed optimizations backfire?

Some fixes make a report look better and the site worse. I undo these in audits more often than I would like:

  • Stacking optimization plugins. Two plugins minifying and combining the same files, or a caching plugin on top of a host cache with different purge rules, produce broken layouts and stale pages. Pick one tool per job.
  • Lazy loading everything. Lazy loading the hero image delays the LCP, sometimes by a lot. Lazy loading is for images below the fold.
  • Preloading too much. A preload tells the browser “this matters most”. Preload ten files and nothing matters most, and the LCP image waits in line with fonts and scripts.
  • Combining all CSS and JavaScript into one file. With HTTP/2 and HTTP/3, many small files are not the problem they were. One huge bundle often means every page downloads code for every other page.
  • Delaying scripts the page needs. If the menu, the add-to-cart button or the search box only works after a delayed script loads, the first interaction is slow and INP gets worse.
  • Cleaning the database with a one-click tool on production without a backup, and without knowing which plugin owns which table.
  • Optimizing for the lab score. Removing the cookie banner or the chat widget only for Lighthouse user agents is cloaking, and it changes nothing for visitors.

The pattern behind all of them is the same: a change made without measuring its effect on real visitors. That is why I measure before and after every change, one change at a time, on a staging copy when the change is risky.

What does a speed-up project look like in practice?

When I work on a site, the sequence is roughly the same regardless of size. First a few days of measuring: field data, per-template lab runs, server timings and a plugin and tag inventory. Then a written list of bottlenecks ranked by impact and effort, with the server and cache items near the top because they help every page. Then implementation in small batches, each one deployed and checked on its own. Finally a month of watching field data catch up, because of the 28-day window.

The ranking step is the part people skip. It is tempting to start with whatever the PageSpeed report lists first. That list estimates savings for one URL in one lab run. It says nothing about what moves your field data across the whole site. A slow TTFB on every uncached request rarely tops that list, yet it is often the biggest win.

How many plugins is too many?

There is no number. I have seen fast sites with a long plugin list and slow sites with a short one. What matters is what each plugin does on each request: queries it adds, assets it loads on the front end, external HTTP calls it makes, cron jobs it schedules. One bad plugin that makes a remote API call on every page load costs more than twenty small ones that do nothing on the front end.

Query Monitor shows queries and HTTP calls grouped by component. The diagnostic guide explains how to use it to find the plugin that is slowing the site down, without the old trick of deactivating everything on production.

How do you prove the site got faster, and keep it that way?

With the same field data you used for the baseline. Remember the 28-day window: CrUX and the Search Console report take about four weeks to fully reflect a change, so a fix deployed today won’t show its full effect tomorrow. Lab tools give you quick feedback while you work. Field data tells you whether it worked for visitors.

To keep it fast after the project ends:

  • add real user monitoring if you can, so you see regressions in days rather than weeks
  • run Lighthouse or a similar check on key templates in your deploy process to catch obvious regressions
  • review new plugins and tags before they go live, not after the report turns red
  • recheck autoloaded data and slow queries a few times a year
  • keep PHP and WordPress updated, since both regularly ship performance work

Sites with many editors, several teams and a long list of integrations need this more than most. That is a big part of what I mean by enterprise WordPress: performance as a process with owners, not a one-off cleanup.

Frequently asked questions

Is a caching plugin enough to speed up WordPress?

For a small content site on decent hosting, a well-configured page cache solves most of the TTFB problem. It doesn’t fix a heavy theme, an unoptimized LCP image or third-party scripts, and it does nothing for uncached pages like carts and dashboards. A caching plugin is one layer of the job.

Will a 100 PageSpeed score improve my rankings?

The PageSpeed score is a lab result from Lighthouse and Google doesn’t use it for ranking. Google uses Core Web Vitals from field data as part of its page experience signals. Aim to pass LCP, INP and CLS for real visitors. A green lab score that doesn’t match your field data is not worth chasing.

How long does it take to see results after speeding up WordPress?

Your own measurements change immediately. CrUX field data, which feeds PageSpeed Insights and Search Console, is a 28-day rolling window, so expect about four weeks before the reports fully show the change.

Do I need a CDN?

If your visitors are spread across regions far from your server, a CDN shortens the distance for static files and, when configured to cache HTML, for the page itself. If almost all visitors are near the server and the page cache is fast, a CDN helps less. Measure TTFB from where your visitors are before deciding.

Should I switch from a page builder to Gutenberg for speed?

Not automatically. A rebuild is expensive and a disciplined builder site can pass Core Web Vitals. If the site is due for a redesign anyway, a block theme usually ships less CSS and JavaScript for the same layout. Compare the two on your own templates first.

Want a second pair of eyes on your site?

If you would rather have the bottlenecks found and ranked for you, I run a WordPress performance and Core Web Vitals audit that goes layer by layer, from server response to third-party scripts, with field data as the reference. For ongoing work on larger sites, see how I work as a WordPress performance specialist; implementation is done by the WebOption team.

Work with Daniel More in Performance