PERFORMANCE
Why is my WordPress site slow? A practical fix list
By Anupa Dinuranga, FounderUpdated 8 min read
Measure before you change anything
Installing an "optimisation" plugin before you know what is slow is how sites end up with three caching plugins fighting each other. Start with a measurement you can repeat.
Run your homepage and one or two typical inner pages (a blog post, a product page) through PageSpeed Insights. Look at the mobile results first; they are usually worse. The report has two parts:
- Field data ("Discover what your real users are experiencing") comes from real Chrome users over the last 28 days. It only appears if your site has enough traffic. This is what Google uses for Core Web Vitals.
- Lab data is a single Lighthouse test from Google's servers on a simulated device and network. It changes between runs, but it tells you why a page is slow.
The three Core Web Vitals and Google's "good" thresholds:
| Metric | What it measures | Good |
|---|---|---|
| LCP (Largest Contentful Paint) | When the main content, often a hero image or heading, has rendered | 2.5 s or less |
| INP (Interaction to Next Paint) | How quickly the page responds to taps, clicks and key presses | 200 ms or less |
| CLS (Cumulative Layout Shift) | How much the layout jumps around while loading | 0.1 or less |
Write the numbers down. The fixes below are in rough order of how often they make the biggest difference, but your report decides the order for your site. Fix the largest problem, then measure again.
Fix 1: Slow server response (TTFB)
Time to First Byte is how long the server takes to start sending the page. If it is slow, everything after it is slow too, and no image optimisation will hide it. You can check it from any terminal:
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}s\n" https://example.com/Run it a few times. If the first byte regularly takes more than about a second on an uncached page, the server is struggling to run PHP. The usual causes are:
- Not enough CPU. WordPress builds each uncached page by running PHP and database queries. On crowded shared hosting, your site waits for CPU time.
- An old PHP version. Newer PHP 8 releases run WordPress noticeably faster than old versions and still get security fixes. Check the versions listed on WordPress's requirements page and test your plugins against a current one.
- No caching at all, which the next two fixes address.
Fix 2: Page caching and a CDN
Page caching saves the finished HTML of a page and sends that copy to the next visitor, instead of running PHP and the database again. For a blog or company site where most visitors are not logged in, this is the single biggest win.
- Use one page caching solution: your host's built-in cache or a plugin such as WP Super Cache. Two caching layers that don't know about each other cause stale pages and odd bugs.
- Make sure it skips pages that must stay personal: logged-in users, the cart, checkout and account pages on WooCommerce. Good caching plugins handle this, but check.
- Purge the cache after you publish or update content, or confirm the plugin does it automatically.
A CDN then serves your images, CSS and JavaScript from locations close to each visitor, which cuts download time for anyone far from your server. Our guide to putting Cloudflare in front of a server covers the SSL mode and caching rules to get right.
Don't cache full HTML pages at the CDN for a site with logins or a shop unless you have set rules that bypass the cache for logged-in users and cart cookies. Otherwise one customer can see another's cart.
Fix 3: Object caching with Redis
Page caching cannot help pages that are different for each user: the WordPress admin, a logged-in member area, a WooCommerce cart. Those still run PHP and the database on every request.
An object cache stores the results of repeated database lookups in memory. WordPress already has an object cache, but by default it only lasts for a single request. A persistent object cache such as Redis keeps those results between requests, so the database does less work on every uncached page.
It needs a Redis server, the PHP Redis extension, and a plugin such as Redis Object Cache that installs the object-cache.php drop-in. Once it is running, the plugin's settings page or WP-CLI shows whether it is connected:
wp redis statusObject caching matters most for shops, membership sites and busy admin areas. For a small brochure site with page caching, the difference is often small.
Fix 4: Images
Images are usually the heaviest part of a page and often the LCP element. Four things to check:
- Modern formats. WordPress supports WebP and AVIF uploads. Both are much smaller than JPEG or PNG at similar quality. An image optimisation plugin can convert existing uploads.
- Correct sizes. Don't upload a 4000-pixel photo to show it 800 pixels wide. WordPress creates smaller sizes and a
srcsetso browsers can pick one, but only if the theme uses them. - Width and height set. Images without dimensions make the layout jump when they load, which hurts CLS.
- Lazy loading, but not for the LCP image. Below-the-fold images should load lazily. The hero image at the top should not, because lazy loading delays exactly the image LCP is waiting for. Sliders and page builders often lazy-load the hero by mistake.
<img src="/wp-content/uploads/hero-1200.webp"
width="1200" height="600"
fetchpriority="high"
alt="Describe the image">Fix 5: Plugins, themes and page builders
The number of plugins matters less than what each one does. One badly written plugin that runs slow queries on every page costs more than twenty small ones.
Install the free Query Monitor plugin and load a slow page while logged in as an admin. It shows how many database queries ran, which were slow, which plugin or theme triggered them, and any external HTTP requests made while building the page. A plugin calling an external API on every page load is a common culprit.
- Remove plugins you no longer use. Deactivated plugins still need updating if they stay installed.
- Look for plugins that load their CSS and JavaScript on every page when they are only used on one (a contact form, a slider).
- Test changes on a staging copy, deactivating one suspect at a time and measuring again.
- Heavy multipurpose themes and page builders add a lot of HTML, CSS and JavaScript to each page, which hurts LCP and INP. If the theme is the problem, switching is a bigger job, but a lighter theme or the block editor is often the real fix.
Fix 6: Clean up the database
Old sites collect thousands of post revisions, expired transients and leftover options from plugins removed years ago. Take a backup first, then clean up with WP-CLI:
# back up first
wp db export before-cleanup.sql
# remove expired transients
wp transient delete --expired
# see how many revisions you have
wp post list --post_type=revision --format=countTo limit future revisions, add this to wp-config.php above the "That's all, stop editing" line:
define( 'WP_POST_REVISIONS', 10 );The bigger hidden cost is often autoloaded options: settings WordPress loads on every single request. A plugin that stores a large blob here slows every page. WordPress's Site Health screen warns when the total gets large, and this query lists the biggest offenders (change wp_ if your table prefix is different):
SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 20;If a large entry belongs to a plugin you have removed, it is usually safe to delete. If it belongs to an active plugin, check its settings or ask its developer before touching it.
Where NevaraCloud fits
Our WordPress hosting runs on AMD EPYC processors and NVMe storage behind Cloudflare's CDN. The Pro plan adds 2× CPU priority and Redis object caching, which deal with the hosting side of Fixes 1 and 3 for busy WordPress sites and shops. If you would rather have someone do the work, our one-time speed tune-up (LKR 4,500, listed under add-ons) covers caching, image optimisation and Core Web Vitals, with a target load time under 2 seconds.
Hosting won't fix a page builder that ships megabytes of JavaScript, or a plugin making slow external calls. Measure first: if your TTFB is already fast, the fixes in sections 4 to 6 matter more than a move. If you do decide to move, read how to migrate without downtime.