Skip to content
Sign in

Speeding up WordPress without breaking it

Most slow WordPress sites are slow for the same four reasons: uncached pages on weak hosting, too many plugins loading assets everywhere, heavy page builders, and oversized images. Fix them in that order and measure after each step.

DeskSEO editorial team · · 6 min read

A mechanic tunes a vintage motorbike engine in a clean sunlit garage

WordPress itself is not slow. A fresh install with a lightweight theme on decent hosting serves pages quickly. Real WordPress sites get slow because of what is added around the core: hosting that cannot keep up, dozens of plugins each loading scripts on every page, page builders that generate enormous HTML, uncompressed images, and a growing collection of third-party tags. Each of those has a fix, and the order in which you tackle them matters, because the first two usually produce most of the gain.

Before changing anything, take measurements you can compare later: TTFB and Core Web Vitals for the home page, a typical post and a typical product or landing page, on mobile. PageSpeed Insights gives both lab and field data. A DeskSEO check records TTFB and HTML size for the home page on every run, which makes the before-and-after easy to see.

Step 1: server response time and page caching

Without caching, every page view runs PHP, loads WordPress and all active plugins, and queries the database. On shared hosting under load, that can take one to three seconds before the first byte. Nothing on the front end can compensate for that.

Page caching stores the finished HTML and serves it directly to the next visitor. It is the single largest speed improvement for most WordPress sites. Options, from simplest to most robust:

  • Host-level caching: many managed WordPress hosts include a server cache. If yours does, use it and do not add a second caching plugin on top.
  • A caching plugin that writes static HTML files served by the web server.
  • A CDN with HTML caching in front of the site, which serves cached pages from locations close to visitors.

Check that caching actually works: request a page twice and compare TTFB, or look for cache headers in the response. Common reasons it silently fails: cookies set on every page (by some plugins or consent tools) that make the cache treat every visitor as unique, query strings from tracking parameters, and logged-in users testing the site and seeing uncached pages.

If uncached response times are very slow (above a second for a simple page), caching hides the problem but does not solve it. Visitors who miss the cache, crawlers hitting rarely-visited pages, and WooCommerce carts all still pay the full cost. The TTFB guide covers the server side further: PHP version, object caching and slow queries.

Step 2: plugins, measured rather than counted

The question is not how many plugins you have but what each one costs. Two kinds of cost:

  • Back-end cost: database queries and PHP work on every request. A query-monitoring plugin (used temporarily, then removed) shows queries and time per plugin on a given page.
  • Front-end cost: CSS and JavaScript files the plugin adds to pages. Many plugins load their assets on every page even if they are only used on one. A contact form plugin loading its scripts on all 400 blog posts is a typical example.

Work through the list:

  1. Deactivate and delete plugins nobody uses. Old sliders, abandoned social sharing tools and "temporary" helpers accumulate.
  2. Replace plugins that do something trivial with a few lines in the theme, or with a feature the theme or core already has.
  3. For plugins you keep, restrict asset loading to the pages that need them. Some plugins have this setting; asset management plugins can do it for others.
  4. Watch out for plugins that call external services on every page load (stock checkers, social counters, font services), which add network waiting time to server response.
A delivery cyclist rides fast along a quiet sunny street lined with trees

Step 3: theme and page builder weight

Page builders let non-developers create layouts, at a cost: nested wrapper elements, inline styles, and large CSS and JavaScript bundles. A simple page can end up with several thousand DOM nodes and hundreds of kilobytes of assets. This hurts every Core Web Vital: LCP waits for render-blocking CSS, INP suffers from large DOMs and heavy scripts (see fixing INP), and CLS rises when sections load in stages.

Options, depending on how far you can go:

  • Use the builder's own performance settings: many now offer optimised asset loading, reduced DOM output and disabling of unused widgets.
  • Build simpler layouts. Fewer nested sections, fewer animations, no sliders above the fold.
  • Use the block editor with a lightweight block theme for new pages, keeping the builder only where it is genuinely needed.
  • For a redesign, budget for a lighter theme. It is often cheaper than months of optimisation.

Step 4: images

WordPress generates several sizes of each uploaded image and outputs srcset automatically, which is good. Common problems remain:

  • Original uploads of 4000+ pixels used directly in content or as backgrounds. Set maximum upload dimensions and resize existing originals.
  • JPEG and PNG only. Serve WebP or AVIF via a plugin, the host or an image CDN. The image SEO guide compares formats.
  • The hero image lazy-loaded. WordPress adds loading="lazy" to most images and tries to skip the first one, but themes and builders often defeat this. Check that the LCP image is not lazy-loaded; see fixing LCP.
  • Background images set in CSS for hero sections, which are discovered late.

Step 5: CSS and JavaScript delivery

Once the server is fast and the page lean, asset delivery is the remaining lever. Optimisation plugins offer many options; these are the ones that matter most, with their risks:

OptionBenefitRisk
Defer JavaScriptScripts no longer block renderingInline scripts that depend on deferred libraries can break
Delay JavaScript until interactionLarge LCP and TBT gains for third-party scriptsMenus, sliders and forms may not work until the first tap; analytics can undercount
Critical CSS / remove unused CSSFaster first renderUnstyled content flashes or missing styles on some templates
MinifySlightly smaller filesLow; occasionally breaks badly written scripts
Combine filesFewer requestsMostly unnecessary over HTTP/2; can make caching less efficient
Preload fonts, local fontsFaster text rendering, fewer layout shiftsLow

Enable one option at a time, then test the pages that matter: the menu on mobile, forms, the cart and checkout if you have one, logged-in views and any interactive widget. Clear all caches between tests.

Step 6: third-party scripts

Chat widgets, heatmaps, multiple analytics tools, ad pixels, embedded social feeds and review widgets often weigh more than the site itself. List every external script loaded on a typical page (the network panel filtered by third-party domains), and for each ask who uses its data. Remove the ones nobody can name an owner for. For the rest, load them after the page is interactive, or only on the pages where they are needed. A chat widget loaded only on pricing and support pages, or only after the user clicks "Chat", costs nothing elsewhere.

Step 7: the database and background work

Over years, WordPress databases collect post revisions, expired transients, spam comments and orphaned data from deleted plugins. A bloated options table with large autoloaded entries slows every uncached request. Cleaning revisions and expired transients, and checking the size of autoloaded options, is worth doing once a year. Also replace the built-in WP-Cron, which runs scheduled tasks on visitor page loads, with a real server cron job on busy sites.

WooCommerce and membership sites

Shops and membership sites have pages that cannot be fully cached: the cart, checkout, account pages, and often any page for logged-in members. For these, server performance matters more than front-end tricks. A current PHP version, a persistent object cache such as Redis where the host supports it, and fewer plugins hooking into every request make a visible difference. Also check WooCommerce's cart fragments script, which on some setups makes an extra uncached request on every page to update the mini-cart; many shops can limit it to pages where the cart is shown.

Measure after each step

Repeat the baseline measurements after each step. Keep a short log: what changed, TTFB, lab LCP, total page weight and number of requests. Speed work on WordPress is full of options that help one site and hurt another, and the log is how you know which is which. Field data in Search Console takes up to 28 days to reflect improvements, so judge by lab data first and confirm with field data later.

Questions

How many plugins is too many?

There is no magic number. One badly written plugin can slow a site more than thirty good ones. What matters is what each plugin loads on the front end and what database work it does per request. Measure, do not count.

Will a caching plugin fix everything?

Page caching fixes server response time for anonymous visitors, often dramatically. It does not fix heavy images, too much JavaScript or layout shifts, and it does not help logged-in users or uncached pages such as carts and checkouts.

Is a CDN worth it for a small WordPress site?

Usually yes, especially if your visitors are spread across countries. Many CDNs have free tiers. For a site with a purely local audience and a well-located host, the gain is smaller.

Should I use a speed optimisation plugin that does everything?

All-in-one optimisation plugins can help, but their aggressive options (combining scripts, delaying JavaScript, removing unused CSS) can break features. Enable options one at a time and test forms, menus, checkout and logged-in views after each.

Keep reading