Key Takeaways
- Slow WordPress sites are almost never WordPress’s fault — the platform itself is fast on clean installs
- The 3 biggest causes are bad hosting (high TTFB), unoptimised images, and theme/plugin bloat
- Each cause can be diagnosed with free tools: PageSpeed Insights, Query Monitor, Chrome DevTools
- Quick wins like image compression, basic caching, and plugin cleanup can cut 2–3 seconds immediately
- Server-level issues require deeper fixes that no plugin can address
Why is your WordPress site crawling?
You built your WordPress site, published your content, maybe even invested in SEO — and then you check your PageSpeed score. 34. Red across the board. Your beautiful site takes 6 seconds to load on mobile, and half your visitors have already left before they see a single word.
I see this every week. Site owners come to us frustrated, convinced WordPress is inherently slow. It’s not. A clean WordPress installation on decent hosting loads in under 800 milliseconds. The problem is never WordPress itself — it’s what’s been piled on top of it.
After optimising over 150 WordPress sites, I’ve found the same 12 causes account for virtually every slow site I encounter. Here’s each one, how to diagnose it with free tools, and exactly how to fix it. Slow sites fail Core Web Vitals — and that directly costs you Google rankings.
1. Cheap or misconfigured hosting
Your server’s response time — measured as TTFB (Time to First Byte) — sets the absolute floor for your page speed. If your server takes 800ms to start sending the HTML, nothing you do in WordPress will make your site fast. You’re starting 800ms behind before the browser even begins rendering.

Shared hosting is the most common culprit. You’re sharing CPU, RAM, and disk I/O with hundreds of other sites on the same server. When your neighbour’s site gets a traffic spike, your site slows down. We’ve measured TTFB of 1.5–2 seconds on shared hosting — that’s 1.5 seconds of your visitor staring at a white screen.
How to diagnose: Open Chrome DevTools, go to the Network tab, reload your page, and click the first HTML document request. The “Waiting for server response” time is your TTFB. If it’s over 600ms, hosting is your primary bottleneck.
How to fix: Upgrade to managed WordPress hosting (Cloudways, Kinsta, or Closte) or, at minimum, upgrade your PHP version and enable server-level caching. Moving from shared hosting to a properly configured VPS typically cuts TTFB to under 200ms. Read our detailed WordPress hosting comparison for speed for specific recommendations.
2. Unoptimised images
Images are the single biggest payload culprit on most WordPress sites. I regularly audit sites where the homepage loads 15–20MB of images — full-resolution PNGs uploaded straight from Photoshop at 3000px wide, served to a 375px mobile screen with no lazy loading and no responsive sizing.
A single unoptimised hero image can be 3MB. That’s larger than the rest of the page combined. On a 4G mobile connection, that single image takes 3–4 seconds to download.
How to diagnose: Open Chrome DevTools, go to the Network tab, and filter by “Img”. Sort by size. If any image is over 200KB, or if total image weight exceeds 1MB, you have a problem. Also check the Coverage tab — if images above the fold are lazy loaded, your LCP score will suffer.
How to fix: Convert all images to WebP format (30–50% smaller than JPEG at equivalent quality). Compress to quality 80 — it’s visually indistinguishable from 100 for photographic images. Add proper width and height attributes to prevent layout shifts. Lazy load everything below the fold, but keep your LCP image set to loading="eager". Our image optimisation guide covers the full process.
3. Too many plugins
The average WordPress site has 20–30 active plugins. Each one hooks into WordPress’s execution flow, adds its own CSS and JavaScript files to the frontend, and runs database queries on every page load. The cumulative effect is massive.

I audited a client’s site last month that had 42 active plugins. Eleven of those were some form of optimisation or caching plugin — fighting each other for control of the same resources. The site scored 28 on PageSpeed Insights.
How to diagnose: Install Query Monitor on your staging site. It shows you exactly how much time each plugin consumes, how many database queries each one runs, and how many scripts and styles each one loads. Sort by impact and identify the worst offenders.
How to fix: Audit every active plugin against three questions: Does this do something I actually need? Is there a lighter alternative? Can this functionality be achieved with a code snippet instead? Remove every plugin you’re not actively using — deactivated plugins don’t affect performance, but deleted is better than deactivated. Aim for under 15 active plugins. Running a WooCommerce store? Plugin bloat is even more damaging — see our WooCommerce speed optimisation guide for ecommerce-specific fixes.
4. Bloated theme or page builder
This is the single biggest cause of slow WordPress sites, and the one most people underestimate. Multipurpose themes like Avada, Divi, and Enfold load 500KB–2MB of CSS on every page. Page builders like Elementor generate enormous inline styles and JavaScript payloads.
Here’s the real problem: a typical Elementor page loads the entire framework CSS — 400KB+ — even though only 15–20% of those styles apply to the current page. That’s 300KB+ of render-blocking CSS the browser must download and parse before it can paint a single pixel. On a 4G connection, that alone takes 1–2 seconds.
How to diagnose: Open Chrome DevTools and go to the Coverage tab (Ctrl+Shift+P, type “coverage”). Reload your page. It shows the exact percentage of CSS and JavaScript that’s actually used. If your main CSS file shows 80%+ unused code, your theme is the problem.
How to fix: Enable your theme’s built-in performance features (most modern themes have asset optimisation settings). Use a tool to strip unused CSS. For maximum impact, rebuild critical page templates with clean, purpose-built code — this is what we do for every VeloPress client, and it consistently delivers the largest performance gains.
5. No caching
Without caching, WordPress rebuilds every page from scratch on every single visit. That means executing PHP, running 80+ database queries, assembling the HTML, and sending it to the browser — every time. A page that could be served in 20ms from cache takes 600ms+ to generate dynamically.
How to diagnose: Check your HTTP response headers. In Chrome DevTools Network tab, click the HTML document and look for headers like X-Cache: HIT, X-Varnish, or CF-Cache-Status. If none exist, you have no page caching. Also check for an X-Redis or X-Object-Cache header — if missing, you don’t have object caching either.
How to fix: Implement all four caching layers: page cache (so WordPress doesn’t rebuild pages), object cache with Redis or Memcached (so repeated queries come from memory), browser cache (so return visitors load instantly), and CDN cache (so files are served from edge nodes near your visitors). Read our complete WordPress caching guide for step-by-step setup.
6. Render-blocking CSS and JavaScript
When the browser encounters a CSS file or synchronous JavaScript file in the <head>, it stops rendering the page until that file has fully downloaded and been processed. This is called render blocking, and it’s one of the most common PageSpeed warnings.
A typical WordPress site loads 5–10 CSS files and 8–15 JavaScript files. If they’re all render-blocking, the browser has to download and parse them sequentially before painting anything. On mobile, this can add 2–4 seconds of blank white screen.
How to diagnose: Run PageSpeed Insights and look for the “Eliminate render-blocking resources” audit. It lists every CSS and JS file that blocks rendering, along with the estimated time savings from fixing each one.
How to fix: Defer non-critical JavaScript using the defer attribute. Inline critical CSS (the styles needed for above-the-fold content) directly in the <head> and load the rest asynchronously. This is one of the highest-impact optimisations you can make — it often improves LCP by 1–2 seconds.
7. Database bloat
WordPress stores everything in a MySQL database, and over time it accumulates enormous amounts of unnecessary data. Post revisions (WordPress keeps unlimited revisions by default), expired transients, orphaned metadata, spam comments, and bloated autoloaded options.
I recently audited a site with 47,000 post revisions, 12,000 expired transients, and 8MB of autoloaded options (it should be under 800KB). Every page load queried against these bloated tables, adding 300–400ms to the server response time.
How to diagnose: Run wp option list --autoload=yes --format=csv | awk -F',' '{sum+=length($2)} END {print sum/1024/1024 " MB"}' in WP-CLI to check autoloaded data size. If it’s over 1MB, you have a problem. Query Monitor also shows slow queries and their execution times.
How to fix: Clean post revisions (limit to 5 in wp-config.php with define('WP_POST_REVISIONS', 5);), delete expired transients, remove orphaned metadata, and optimise table structures. For ongoing performance, implement Redis object caching so repeated queries are served from memory. See our database optimisation guide for the complete process.
8. No CDN
Without a CDN, every asset — images, CSS, JavaScript, fonts — is served from your single origin server. A visitor in Edinburgh requesting files from a server in Virginia adds 100–150ms of network latency to every request. Multiply that by 30–50 assets per page, and you’ve added seconds to the load time.
How to diagnose: Look at your asset URLs. If all your CSS, JS, and images are served from your own domain with no CDN subdomain or CDN-specific headers, you’re serving everything from origin.
How to fix: Set up Cloudflare (the free tier is enough for most sites). It caches your static assets on edge servers worldwide, so visitors get files from the nearest node. A visitor in London gets files from a London edge server, not from your origin in the US. The difference is dramatic — asset load times drop by 50–80%.
9. External scripts and third-party bloat
Google Analytics, Facebook Pixel, Google Tag Manager, chat widgets, reCAPTCHA, hotjar, intercom — each one adds DNS lookups, TCP connections, and JavaScript execution. A single chat widget can add 500ms to your page load. Stack five third-party services, and you’ve added 1–3 seconds that you have zero control over.
How to diagnose: Run your site through WebPageTest and examine the waterfall. Third-party requests are highlighted in a different colour. Count them and note their load times.
How to fix: Audit each third-party script against its actual value. Remove anything you’re not actively using. Self-host scripts where possible (like Google Fonts). Defer everything that isn’t critical for above-the-fold rendering. For analytics, consider lightweight alternatives like Plausible or Fathom that add 1KB instead of 45KB.
10. Large or unoptimised fonts
Loading Google Fonts with 5+ weights, no font-display declaration, and no preloading causes two problems: the DNS lookup to fonts.googleapis.com adds 100–200ms, and the font files themselves can total 200KB+. Without font-display: swap, the browser shows invisible text until fonts finish loading — the dreaded FOIT (Flash of Invisible Text).
How to diagnose: In Chrome DevTools, filter the Network tab by “Font”. Check how many font files load, their total size, and whether they’re served from a third-party domain.
How to fix: Self-host your fonts (eliminates the third-party DNS lookup). Subset them to include only the characters you need. Use font-display: swap or font-display: optional so text renders immediately. Preload the most critical font file with <link rel="preload">. Or use system fonts — they load in 0ms and look perfectly fine.
11. PHP version out of date
PHP 7.4 is 40–60% slower than PHP 8.2+. WordPress core and every plugin runs on PHP, so an outdated version means every single operation takes longer. If you’re still on PHP 7.4 (or worse, 7.2), upgrading is the single easiest performance win available.
How to diagnose: Check your WordPress admin dashboard under Tools → Site Health. It shows your PHP version. Or run php -v via SSH. Anything below 8.1 needs upgrading.
How to fix: Upgrade to PHP 8.2 or 8.3 through your hosting control panel. Test on staging first — most modern plugins and themes are compatible, but older ones may throw deprecation warnings. The performance improvement is typically 30–50% with zero code changes. Read our hosting guide for PHP version recommendations by host.
12. No Brotli or Gzip compression
Without compression, your HTML, CSS, and JavaScript files are transferred at their full uncompressed size. Brotli compression reduces file sizes by 60–80%. A 400KB CSS file becomes 80KB. A 100KB HTML document becomes 20KB. The transfer time savings on mobile are substantial.
How to diagnose: Check your response headers in Chrome DevTools. Look for Content-Encoding: br (Brotli) or Content-Encoding: gzip. If neither is present, compression isn’t enabled.
How to fix: Enable Brotli at the server level (Nginx: brotli on; in your config, Apache: mod_brotli). If your host doesn’t support Brotli, enable Gzip as a fallback. Cloudflare enables Brotli automatically on all plans, which is another reason to use it.
What to do next
If you’ve identified 3 or more of these issues on your site, you’re leaving significant performance — and revenue — on the table. Start with the quick wins: compress your images, set up basic caching, remove unused plugins. These changes alone typically cut 1–3 seconds from load times with minimal risk.
If you’re still scoring below 70 after the quick wins, the remaining issues are almost certainly server-level problems. Misconfigured hosting, no object caching, outdated PHP, missing Brotli compression — these require engineering solutions that no plugin can provide.
Our complete WordPress speed guide covers the full optimisation stack from server to delivery. If you want to know exactly what’s wrong with your specific site, our speed testing guide shows you how to measure properly.
Frequently asked questions
How can I tell which plugin is slowing down my WordPress site?
Install Query Monitor on your staging site. It shows exactly how much execution time, how many database queries, and how many scripts each plugin adds. Sort by total impact to identify the worst offenders. You can also use the Health Check & Troubleshooting plugin to disable plugins one at a time and measure the impact.
Will installing a caching plugin fix my slow WordPress site?
Partially. A caching plugin addresses one of the twelve causes listed here — specifically the page caching layer. It won’t fix hosting issues, image bloat, theme bloat, database problems, or any of the other causes. Think of it as one tool in a twelve-tool toolkit. It helps, but it’s not a complete solution.
What is a good TTFB for a WordPress site?
Under 200ms for cached pages and under 600ms for uncached dynamic pages. If your TTFB is consistently over 600ms, your server configuration or hosting is the primary bottleneck. Google considers a TTFB under 800ms acceptable, but for competitive search rankings, aim for under 200ms on your key landing pages.
Is WordPress inherently slower than other platforms?
No. A clean WordPress installation loads in under 800ms. WordPress’s reputation for being slow comes from how people use it — bloated themes, dozens of plugins, cheap hosting, and unoptimised content. Properly optimised, WordPress can score 100 on PageSpeed Insights and deliver sub-second load times. This site proves it.
How many plugins is too many for WordPress performance?
There’s no magic number — a well-coded plugin that runs efficiently has minimal impact, while a single poorly-coded plugin can add seconds to load time. That said, most high-performing WordPress sites run 10–15 active plugins. If you’re over 25, you almost certainly have redundancy and conflicts. Quality matters more than quantity, but fewer is generally better.
Tired of diagnosing speed issues?
We find and fix all 12 causes — guaranteed
Our free audit identifies exactly which issues are slowing your site. Then we fix every one of them.