Most slow WordPress sites we open up are slow for boring reasons. A 5 MB photo sits in the hero. There’s no page cache, so the server builds every page from scratch for every visitor. A chat widget loads on every page, including the privacy policy. And there are thirty-odd plugins, a few of which nobody remembers installing.
You can fix almost all of that without a rebuild, if you go in the right order. This is the checklist we work through, biggest payoff first. Get as far as images and caching and you’ve done most of the good. Work on a staging copy if your host offers one, and take a full backup before you change anything.
First, measure
1. Get real numbers before you touch anything
Open PageSpeed Insights at pagespeed.web.dev and run a URL. The top section is field data. It comes from the Chrome User Experience Report: what real Chrome users experienced on your page over the previous 28 days. Below that is lab data, one simulated page load run by Lighthouse. Lab data helps with debugging. Field data is what visitors actually got. Pages with too few visits fall back to whole-site figures, and a small site may have none at all. Then the lab numbers are your rough guide.
Google counts a page as good when at least 75% of visits meet these marks:
- Largest Contentful Paint (LCP) of 2.5 seconds or less: how long the main content, often the hero image or headline, takes to appear.
- Interaction to Next Paint (INP) of 200 milliseconds or less: how quickly the page reacts to a tap or click.
- Cumulative Layout Shift (CLS) of 0.1 or less: how much things jump around while loading.
Don’t stop at the homepage. Test the four or five pages that bring in money or enquiries, such as your main service page, a popular blog post and the contact page. Look at mobile first, since that’s where most sites struggle. Write the numbers in a simple sheet. You’ll want them later, to prove the work paid off and to catch any fix that made things worse.
While you’re in the dashboard, open Tools → Site Health. Since WordPress 6.1 it checks whether a page cache is detected and whether the server responds quickly enough (its default line is 600 ms).

The big, cheap wins
2. Fix your images
Images are usually the heaviest thing on a page, and the hero is often the LCP element itself. Start with size. A photo straight off a phone can be 4,000 pixels wide and several megabytes, and no image needs to be wider than the space it fills. For a full-width hero we rarely go past 2,000 pixels. Inside a blog post, 1,200 is plenty. Resize before you upload.
Then the format. WordPress has accepted WebP since version 5.8 and AVIF since 6.5, if your server’s image library supports it (Site Health → Info → Media Handling tells you). When WebP support landed, the WordPress team put it at around 30% smaller than JPEG or PNG on average. The free Modern Image Formats plugin, from the WordPress Performance Team, converts new JPEG and PNG uploads for you. Older images need regenerating, for example with Regenerate Thumbnails.
Lazy-loading you mostly get for free: since 5.5, WordPress adds loading="lazy" to images by default, so no plugin is needed. The thing to check is the opposite problem. Google’s tests on WordPress sites found that lazy-loading images in the first screen made LCP slower. Core now tries to leave that first big image alone, and since 6.3 marks it fetchpriority="high". Some themes and page builders output images their own way, though. Right-click your hero image, choose Inspect, and make sure it doesn’t say loading="lazy".
3. Turn on page caching, then add a CDN
Without a cache, WordPress builds each page afresh for every visit. A page cache saves the finished page and hands out copies. WordPress’s own documentation says this can improve performance “several hundred times over” for fairly static pages. On a brochure site or blog, it’s often the biggest win here.
Check what your host already does first, because plenty cache at the server level. If your host runs LiteSpeed, use the LiteSpeed Cache plugin, whose page caching only works on LiteSpeed servers. Elsewhere, WP Super Cache from Automattic is simple and dependable. Use one page cache. Two stacked caches fight, and you won’t know which broke things.
Next, add a CDN, which keeps copies of your images, CSS and JavaScript on servers close to your visitors. If your server is in the US and your customers are in Pune, that distance shows. WordPress’s docs note that a CDN works best alongside a caching plugin. Cloudflare’s free plan includes one and is enough for most small sites.
Afterwards, check time to first byte (how long the server takes to start replying). Google calls 0.8 seconds or less good; a cached page should beat that easily.
Find what’s weighing the site down
4. Audit your plugins
Counting plugins tells you little; one badly built plugin can do more harm than twenty good ones. To find the expensive ones, install Query Monitor (free, 200,000+ active installs). Its admin-bar panel lists the database queries on each page, grouped by the plugin or theme responsible, and flags slow and duplicate ones. It also times outgoing HTTP requests, so a plugin that phones some outside server on every page load shows up fast.
Then go through Plugins → Installed Plugins and ask of each: do we still use it, and is there a lighter way? On staging, deactivate suspects one at a time and re-test your main pages, which is the method WordPress’s own optimisation guide recommends. Delete what you don’t need, because a deactivated plugin is still code on your server.
Our usual suspects: homepage sliders, all-in-one plugins used for one feature, share counters and related-posts plugins.
5. Look at your theme, page builder and fonts
We like page builders (this site is built with Divi), but they can add a lot of CSS, JavaScript and nested markup. Most now have performance settings, such as loading only the CSS a page uses, so go through those before you blame the builder. With an old multipurpose theme that loads every feature everywhere, a leaner theme is sometimes the real fix, but do the rest of this list first.
Fonts cost you more quietly. Every family and weight is a separate file. Open your browser’s developer tools, go to the Network tab, filter by Font and reload. Eight font files? Cut back to two families and only the weights you use. Google’s web.dev guidance is to serve WOFF2 with font-display: swap, so text shows straight away. WordPress’s Font Library (Appearance → Fonts since 7.0, for classic and block themes) can install Google Fonts on your own server instead of loading them from Google’s. Page builders often load fonts their own way, so check there too.
6. Rein in third-party scripts
Chat widgets, ad pixels, heatmaps, YouTube embeds, review badges, booking widgets. Each loads code from someone else’s server, and you don’t control how heavy it is. They can hurt INP as well as load time, because their JavaScript can keep the browser busy right when a visitor taps a button.
Google’s web.dev advice is blunt: if a script doesn’t add clear value to your site, remove it. For whatever survives:
- Load it only where it’s needed. A booking widget belongs on the booking page, not every blog post.
- Add
asyncordeferto scripts that aren’t needed to draw the page. - Use a facade for chat and video: a light placeholder that looks like the real thing and loads the full embed only on click. Google’s Lighthouse documentation names YouTube, Vimeo, Intercom and Drift as good candidates.
- Check your tag manager, where old tags quietly pile up.
Under the bonnet
7. Update PHP and check your hosting
PHP is the language WordPress runs on, and newer versions are generally faster. WordPress recommends 8.3 or newer. According to PHP.net, 8.2 gets security fixes only until 31 December 2026, and 8.1 and older are already unsupported. Your version is under Site Health → Info → Server, and you change it in your hosting control panel. Test on staging first, because old plugins sometimes break on a new PHP version.
If cached pages are now fast but uncached ones (cart, checkout, search, the admin) still drag, the server may be the bottleneck. Ask your host about a persistent object cache such as Redis, which WordPress’s docs say cuts repeated database queries; WooCommerce shops and membership sites gain the most. Shared hosting is fine for a small brochure site with good caching. When it stops being enough, a better plan usually costs less than paying someone to squeeze out milliseconds.
8. Tidy the database
Over the years the database fills with revisions, spam, expired transients and plugin leftovers. Cleaning it rarely transforms a site, but it helps, especially in the admin. Start with autoloaded options, the settings WordPress loads on every request. Site Health warns when they pass 800 KB, and old plugins are the usual cause. WP-Optimize can clear out revisions, spam, trashed posts and transients. Then cap future revisions with one line in wp-config.php:
define( 'WP_POST_REVISIONS', 5 );
Back up the database before any cleanup. Every time.
What not to bother with
- Chasing a perfect 100. Lighthouse’s own documentation says a perfect score is extremely difficult and not expected; 90 and above is already green. Scores wobble between runs anyway, and your Core Web Vitals pass or fail on field data, not this lab number.
- Stacking optimisation plugins. Two caching plugins plus a separate minifier tend to add up to a broken layout. One tool per job.
- Old “speed tweak” lists. Removing query strings from file URLs and similar tricks save very little.
- Moving host before you’ve measured. Sometimes the host is the problem. Often it isn’t.
The checklist in one place
- Test your main pages in PageSpeed Insights, mobile first, and note LCP, INP and CLS.
- Resize images, use WebP or AVIF, and keep the hero out of lazy-loading.
- One page cache, plus a CDN.
- Query Monitor, then deactivate and delete what you don’t need.
- Trim builder features and fonts.
- Remove, restrict or delay third-party scripts.
- PHP 8.3 or newer; better hosting if uncached pages stay slow.
- Clean the database and cap revisions.
Then run step 1 again and compare. Field data covers 28 days, so look once more in a month.
Sources and further reading
- Web Vitals — web.dev
- About PageSpeed Insights — Google for Developers
- Lighthouse performance scoring — Chrome for Developers
- Time to First Byte (TTFB) — web.dev
- New cache Site Health checks in WordPress 6.1 — Make WordPress Core
- WordPress 5.8 adds WebP support — Make WordPress Core
- WordPress 6.5 adds AVIF support — Make WordPress Core
- Modern Image Formats — WordPress.org Plugins
- Lazy-loading images in 5.5 — Make WordPress Core
- The performance effects of too much lazy loading — web.dev
- Image performance enhancements in WordPress 6.3 — Make WordPress Core
- Optimization — WordPress Advanced Administration Handbook
- LiteSpeed Cache — WordPress.org Plugins
- WP Super Cache — WordPress.org Plugins
- Cloudflare Free plan — Cloudflare
- Query Monitor — WordPress.org Plugins
- Best practices for fonts — web.dev
- The Font Library — WordPress.org Documentation
- Load third-party JavaScript — web.dev
- Lazy load third-party resources with facades — Chrome for Developers
- Supported versions — PHP.net
- Requirements — WordPress.org
- Options API: Disabling autoload for large options — Make WordPress Core
- WP-Optimize — WordPress.org Plugins
- Editing wp-config.php — WordPress Advanced Administration Handbook
Image credits: Banner photo by Florian Steciuk on Unsplash. Photo by William Warby on Unsplash.


