Performance Optimization

Performance Quick Start Guide: Solving WordPress Performance Problems

Published · Last updated

Since 2016 I have been solving WordPress performance problems. The performance issues that actually slow a site down are nearly always server-side, and there are a handful of repeatable patterns you can use to find exactly where the slow bottlenecks on your site are coming from.

Below, I pass that knowledge on to help you get the speed you deserve from the hosting you are paying for.

Faster sites make more money, get more social shares, have higher pages per visit, more returning visitors and get crawled more by Googlebot, along with higher search rankings. But most of all, faster sites are better for your users. You love your users, right?

The one idea to take away

Speed-testing tools grade the browser. Your real problem is almost always page generation time on the server, and that is what this guide teaches you to measure and fix.

The most common WordPress performance issues

Nearly every slow site I look at has one or more of these. Each one links to the section that fixes it.

Page generation time: the number that actually matters

What counts as a high page generation time?

Measured uncached on WordPress: under 500ms is good, over 1 second is bad, and over 3 seconds is dreadful. It is not only about how long a single visitor waits. Every page being generated ties up a PHP worker for that entire time, so at over 3 seconds you support far fewer simultaneous visitors and you will struggle to survive a traffic rush. I built Scalability Pro specifically to drag that number back down into the good range.

This section is the short version. For the full treatment – what the number contains, every common cause, and how to find which plugin is responsible on your own site – see WordPress page generation time: how to measure it and bring it down.

Scanning your site with GTmetrix can help identify areas where you could optimise speed, particularly on the Mobile tab where it simulates devices with less CPU power. These tools are useful for spotting when too much is going on in a page for phones to handle.

GTmetrix performance report for the Super Speedy Plugins home page
GTmetrix provides useful pointers for reducing the payload of your site (how big your pages are and how long they take to load in the browser)

These tools will tell you to minify your CSS, compress or resize images, remove render-blocking JavaScript and combine files so they download faster. Many of those recommendations date from before HTTP/2 and HTTP/3, which download many files in parallel over a single connection, so they matter far less than they used to. Running a scan still does no harm and often surfaces something useful. To take advantage of HTTP/3, upgrade your hosting or put a CDN that supports it in front of your site.

Performance Tip

GTmetrix and Pingdom load your page in a browser. They cannot see what your server is doing to build the page. If the page is still slow after you have followed their advice, your page generation time is the culprit.

A slow page generation time is not just a performance issue, it is also a scalability issue. If your server takes 4 whole seconds to generate a page, it is not sitting there chilling. It is doing several things as fast as it can. The resource bottlenecks tend to be CPU and disk, so if you see low CPU but long page loads then you probably have slow disks, or plugins or theme code reading too much data from disk.

Did you know?

Cutting page generation from 4 seconds to 0.5 seconds is not just faster for one visitor. It is 8x less server work per page, so the same hardware handles roughly 8x more traffic and lets search engines crawl 8x more of your pages.

To see the page generation speed on every page of your site, and to start identifying the sources of your performance problems, install the free Query Monitor plugin by John Blackbourn.

Query Monitor showing page generation time in the WordPress admin bar
Install and activate the Query Monitor plugin to see your page generation speed

Page caching should ideally be handled at server level

You probably have a page cache already. You might even have two, which is pointless and wasteful of disk: with multiple page-caching plugins enabled, every page is written to disk multiple times yet only one of those cache files is ever served. Page caching is often the first thing people add to a WordPress site when things get slow.

Common mistake

Running two page-caching plugins does not double your speed. Every page just gets written to disk twice and only one copy is ever served, so all you gain is wasted disk and confusing cache-clearing behaviour.

Page caches are great for reducing server load and surviving traffic spikes, but they do not improve your page generation speed.

If your host does not offer page caching of some kind, change hosts or follow our stack-building guide to get the highest performance at the lowest cost.

If you insist on using a WordPress plugin for page caching then WP Rocket, W3 Total Cache and a myriad of others will do the job. Page caching is trivial to code, so there is not much they can get wrong. Your page-caching plugin should be able to selectively wipe cache entries when posts or products are updated, rather than wiping the entire cache, and it should interface with Apache, Nginx or LiteSpeed so the web server bypasses PHP when a cached file is available.

Object caching is essential

Plugins tend to grab data from the database, manipulate it in some way and store it in an object for use throughout their code while generating the page. An object cache lets these objects be stored in memory across many pages, which means the more your site is browsed, the faster it gets.

Object caches really need to live in memory to give the most benefit, and Redis and Memcached are the two most popular that work with WordPress. WordPress plugins keep getting better at using the object cache properly, so get Redis installed on your hosting (most hosts offer it) and add the free Redis Object Cache plugin by Till Kruse, or use W3 Total Cache.

Best practice

Run Redis in memory, not disk-backed. A disk-backed Redis is slower and defeats the point. With the object cache enabled, move from page to page and you will watch the query count per page drop and your page generation time fall.

Enabling Redis object caching in W3 Total Cache settings
Enabling the object cache in W3 Total Cache is easy: set the method to Redis, then tick the box to enable

See our stack-building guide to make sure your hosting provides an in-memory Redis cache.

Many people use WP Rocket and assume it includes an object cache, but it does not. If you use WP Rocket, add the Redis Object Cache plugin too. They complement each other well.

Hosting choices

What matters most from your hosting company is the stack they provide, and the ability to clone your site into dev and staging areas so you can try things out safely. After that it comes down to managed versus self-managed, remote backups and the level of support. Here are the key essentials to look for:

  • NVMe or SSD disks, never HDD
  • 1Gbps networking, not 100Mbps
  • PHP 8.2 or newer. PHP 8 is dramatically faster than PHP 7, and night-and-day versus the PHP 5.6 that some ancient hosts still run
  • MariaDB, Percona or MySQL 8, not MySQL 5.x
  • Redis in in-memory mode for your object cache, or Memcached
  • Nginx or LiteSpeed both scale better than Apache, though this matters less than the items above
  • A page-caching system of some kind
  • An HTTP-level accelerator, whether Varnish, Nginx FastCGI cache, LiteSpeed, or Cloudflare in front of your site
  • A CDN such as Cloudflare, using its features to compress and minify CSS and set long browser-cache expiry on static files

If you follow the WordPress Speed Up and Advanced WordPress groups on Facebook, people tend to prefer GridPane, RunCloud, Cloudways, Kinsta and WP Engine.

I personally love Digital Ocean and Hetzner. With them I can spin up new server clones in a minute and get full control over the server. My million-product demo store loads in sub-second uncached speeds on a $20-per-month Digital Ocean droplet.

If you want the highest performance at the lowest monthly cost and have the skills to DIY, check out my comprehensive WordPress stack-building guide. I use Digital Ocean, but you can use AWS, Google Cloud or wherever you like and get amazing performance for very little money.

If you want that ultra performance with a front-end control panel, there is no-one better than GridPane. Their stack is an evolution of my stack with a great control panel on top that makes building, configuring, cloning and migrating a matter of point and click. GridPane plus Hetzner gives ultra performance at incredibly cheap prices.

Upgrading your current hosting

Obviously it is easier to stay with your current host, so here is a priority list:

  1. Upgrade PHP. PHP 8.x is far faster than PHP 7, and dramatically faster than PHP 5.6.
  2. Add an object cache, either Redis or Memcached.
  3. Upgrade to MySQL 8 or MariaDB.
  4. Add a CDN.

If after all that your speed is acceptable, then it is fine to stay where you are.

Cloning your server

To properly analyse your site you need to be able to deactivate and reactivate plugins and theme features without affecting your users. Visitors can be on your site overnight, so you really need a clone.

Creating a staging clone of a WordPress server
Cloning your server should be easy and is needed to fully optimise it. Ask your host

Ask your host if they can create a staging server (also called a clone) for you. Most can clone your site to a different subdomain so you can experiment with WordPress settings, including activating and deactivating plugins while you optimise performance. The first step in optimising your site is to find out where the problems lie, and the fastest way to do that is to toggle features on and off without affecting your users.

If your host does not provide cloning, a few plugins can clone smaller sites, but for a larger site follow my migration guide for step-by-step instructions on creating a WordPress clone.

Measuring your page generation time with Query Monitor

The free Query Monitor plugin by John Blackbourn shows your page generation time, how many MySQL queries ran to generate the page and how long they took. Subtract the MySQL time from the total page generation time and you have your PHP time.

Query Monitor overview panel showing queries and timing
Query Monitor is one of my favourite tools, great for quickly discovering potential issues

This tells you whether your slowness comes from the database or from the way some plugins are coded, which typically shows up as a high PHP time.

Performance Tip

The speed Query Monitor shows is for the current user level. Admins load extra code, can see hidden posts and can use the editors, so admin pages are always slower than what your visitors experience. Enable the Query Monitor authentication cookie and log out to measure real visitor speed.

Enabling the Query Monitor authentication cookie
Enable the Query Monitor authentication cookie to see page generation speeds for logged-out visitors

Optimising your own site

Start with Query Monitor. Look for high query counts, slow queries and queries that return a lot of rows. On your dev or staging clone, experiment by deactivating the plugins that show high numbers. Test your pages with Redis disabled first, then test again with Redis enabled.

Once you have found the bad plugins, either find alternatives or disable their assets where they are not needed using the free Asset Cleanup plugin from the WordPress repository.

Asset Cleanup plugin disabling a plugin on pages where it is not needed
The Asset Cleanup plugin lets you unload plugins completely on pages where they are not required

Many plugins run slow code on every page, so unloading them until they are needed can really reduce load on your server and speed everything up. You can also contact the plugin developers, screenshot your performance issues and give them proof that their plugin is slowing your site down.

Finding plugins with too many SQL queries

Click Queries by Component to see which plugins are performing the most queries.

Query Monitor Queries by Component showing query counts per plugin
Queries by Component in Query Monitor shows query counts per plugin. Try it with Redis disabled to get a clearer picture

As your WordPress site grows, the number of queries per page tends to increase. Use Queries by Component to see which plugins are causing your high query count. High query counts do not usually have a high total database time, but they do typically incur a high PHP time because of all the objects being built.

If you use WooCommerce shortcodes or filters you will probably see a very high query count on your slow pages. If those high counts are coming from your shop filters or on-sale pages, use my Super Speedy Filters plugin, which filters with SQL instead of loading products into PHP.

Recent five-star reviews of the Super Speedy Filters plugin
Recent reviews of my Super Speedy Filters plugin

If you use a page builder like WPBakery, Elementor or one of the others, it may have inserted WooCommerce shortcodes for you, or they may be built into your theme options.

Object caching can reduce the number of queries in many cases, so try that first if you have a high query count from particular plugins. Otherwise, test how much page-speed boost you get from deactivating the plugin. If you have many variations driving a high query count, an object cache helps a lot because those objects can be reused across product detail and archive pages. On top of that, I frequently see shops using variations where they could use simpler product rules or product add-ons.

Finding plugins with slow SQL queries

Click Queries to view all queries, then click the Time column to sort by time. Many plugins run slow SQL because they were not written to use database indexes. A query that uses an index runs thousands of times faster than one that scans the whole table.

I created Scalability Pro specifically to find and eliminate table scans in WordPress and WooCommerce. It adds good indexes to your tables and rewrites some queries so they actually use those indexes.

Recent five-star reviews of Scalability Pro
Recent reviews of Scalability Pro

When you find a slow query, Query Monitor tells you which plugin caused it. If you find a slow query that object caching or Scalability Pro do not optimise, let me know and I will figure out a fix.

Finding plugins with high row counts

Click Queries to view all queries, then click the Rows column to sort by row count. Plugins that fetch hundreds or thousands of rows to show ten items on a page typically cause high CPU and high RAM usage. Sometimes an object cache reduces the CPU, but RAM usage often stays high. These are frequently the plugins that fetch the entire database and process it in PHP to produce something on your page.

Common mistake

Plugins with very high row counts should usually just be avoided. Find a replacement rather than trying to cache your way out of the problem.

Speeding up CSS, JS and page rendering

If you are keen to get high Pingdom or GTmetrix scores you will need to optimise your CSS and JS. We do not focus too heavily on that ourselves, because what matters is user-perceived speed, but in many cases the rules those tools give you do improve perceived speed.

There are plenty of asset-optimisation plugins that will get you better scores, but the best approach is a CDN that provides image, CSS and JS optimisation. Many CDNs also offer page caching, keeping even more load off your WordPress server.

Performance Tip

Before optimising any CSS or JS, check whether it needs to load at all. If it does not, unload it with Asset Cleanup. The fastest asset is the one you never send.

Speeding up slow imports

If your imports are slow, the biggest win is the importer itself. My Super Speedy Imports plugin is SQL-first and imports or updates products 10x to 1,200x faster than the usual XML importers. Alongside it, Scalability Pro speeds up any importer, especially as your store grows, and you should also read my article on the WordPress image sizes problem.

Over time, the plugins you install register new image sizes and do not remove them when deactivated. It is not uncommon for a site to have 30 registered image sizes. That means every imported image is resized into 30 variants and stored in your uploads folder, which is a lot of extra CPU for resizing and a lot of disk for storage.

Fix the image sizes for your site using the guide above, and use Scalability Pro for large imports. It speeds imports up by deferring term counts until the import completes and by speeding up the wp_postmeta lookups that import tools use to decide whether to insert or update an item.

For the ultimate in import speed, take images off your server altogether with our External Images plugin, which serves images straight from a CDN, S3 or your affiliate feed with nothing downloaded to your server. Delayed Image Import takes the other approach: the import finishes quickly and the images download afterwards in the background.

Before any of that, check you have a real system cron job driving WordPress. Without one, WordPress runs its scheduled work when a visitor happens to hit the site, which is bad twice over: your visitors pay for the work in page speed, and your imports do not run at all during quiet periods.

Recent five-star reviews of the External Images plugin
Recent reviews of my External Images plugin

Speeding up slow sitemaps

I ran a case study on various XML sitemap plugins and the results will surprise you. The fastest sitemap plugin was actually years old and no longer maintained, so I took it over, renamed it Super Speedy Sitemaps, fixed the security issues and now maintain it. The case study includes techniques that optimise sitemap generation by up to 250-fold.

Chart showing dramatic sitemap speed gains from using an index
Making sitemaps use an index brings tremendous speed boosts

If your sitemaps take over a minute to generate, that affects everyone else using your site at the same time, so it is worth optimising. Worse, search engine bots like Googlebot have a limited crawl budget per site, so a slow sitemap means fewer of your pages get indexed and shown in search results.

Speeding up wp-admin

It is annoying when wp-admin gets slow. This is where you and your staff live. An object cache can speed up wp-admin, but sometimes it does the opposite if a plugin is badly coded, or if you have too many or too-large options in your wp_options table.

Scalability Pro provides plenty of options to optimise wp-admin, and my Super Speedy Search plugin helps too by speeding up admin searching as well as front-end searching.

If you are bulk editing items in wp-admin, it is hard to use Query Monitor to isolate the issue because bulk edits happen one at a time over AJAX. To speed up bulk edits, perform a single edit to see the per-item performance profile and optimise that.

Speeding up your wp_options table

Some options are loaded on every page, and in rarer cases the entire wp_options table is fetched. Plugins leave these options behind and they are often huge. Options marked as autoload are loaded on every page, and for admins all options are regularly loaded, so cleaning up your options table can give a decent speed boost on every page.

W3 Total Cache option to stop storing transients in the database
W3 Total Cache gives an option to stop storing transients in the database, reducing database writes

For the full walkthrough, read my knowledge base article on managing the wp_options table and autoload.

Choosing a fast theme

Many themes sold on marketplaces like ThemeForest arrive bundled with third-party plugins. More features sell more themes, and most sites never grow large enough to feel the cost, so the incentive runs against you. Rehub is one notable exception we have found there.

Prefer themes from established companies with a team of developers behind them rather than a single author, and treat lightweight block-based themes as a serious option in their own right. Theme makers worth a look include Themify, Elegant Themes and GeneratePress.

A heavy theme is not automatically a lost cause. A Bulgarian news site running tagDiv’s Newspaper theme took its archive pages from 9.5 seconds to 1.5 seconds uncached, and the owner recorded a walkthrough of what changed. The write-up, with the video, is in speed hacks for the Newspaper theme by tagDiv.

Performance Tip

A theme’s demo site is not evidence. Demos run on tuned hosting with a handful of products. Judge a theme on your own catalogue size, with your own plugins active.

WooCommerce shortcodes and the attribute and price widgets

If you use WooCommerce shortcodes (products on sale, best sellers, most popular products) or the WooCommerce attribute or price widgets, you will see a very high query count in Query Monitor on the pages that carry them. An object cache helps, but the first load of each page is still slow.

You may not realise you are using them. A page builder can insert the shortcodes for you, and some themes build them into their own options screens, so the first sign is often the query count rather than anything you chose. Removing them, or replacing them with faster equivalents, is usually the single biggest win on a category or shop page.

Every plugin mentioned in this guide is built to remove one of the bottlenecks above, from slow queries and imports to filters, search and sitemaps.

More performance guides

This guide is the overview. These go deeper on each part of it.

Imports and product data

Hosting and stack guides

Finding your bottleneck

Configuration and security

Real-world results

Further reading

The companion hub, for a slow product feed rather than a slow site
Trim the autoloaded options that load on every page
See what it indexes and which queries it rewrites
The DIY server recipe behind sub-second loads
Make sitemap generation up to 250x faster

Frequently asked questions

What is a good WordPress page generation time?
Measured uncached, under 500ms is good and over 1 second is bad. Over 3 seconds is dreadful, and at that point you are not only making visitors wait, you are limiting how many of them your server can handle at once.
Why is my WordPress page generation time high?
Almost always one of three things: a plugin running hundreds of queries per page, a single slow query scanning a whole table because it has no index, or a plugin fetching thousands of rows to display ten. Install Query Monitor and sort the queries by time and by rows to see which it is.
Does page caching fix a slow page generation time?
No. A page cache hides the problem from visitors who get a cache hit, and it is well worth having, but it does nothing for your actual page generation time. Logged-in users, the checkout, the cart and anyone hitting an uncached page still wait the full time.
How do I find which plugin is causing my WordPress performance issues?
Use Query Monitor’s Queries by Component panel to see which plugin runs the most queries, then sort all queries by Time and by Rows. My full guide to analysing performance problems with Query Monitor walks through it step by step. Done by hand it means working on a staging clone and deactivating plugins one at a time, which is slow and easy to get wrong, so I am building Super Speedy Performance Analysis, a free plugin that attributes SQL time, row counts and RAM to individual plugins and your theme, then isolates the real culprits by virtually disabling them for its own test requests only – your live visitors are never affected. Register your interest on that page and I will tell you the moment you can download it.

Getting more help

Since 2016 I have been coding plugins that optimise WordPress in one way or another. I have written lots of guides for different scenarios, and I have personally optimised dozens of previously unoptimisable websites.

We run an active Discord server, and it has been a game changer for support and for driving development forward. I want to make performance and scalability easy and available for everyone, so read the articles, browse the knowledge base, and if you cannot find what you need, or you just want some personalised help, you can find me, Dave Hilditch, on our Discord server almost every day.

Welcome message on the Super Speedy Plugins Discord server
The welcome message on our Super Speedy Plugins Discord server

If you like what I am doing, please share my articles widely. I am great at performance optimisation but I suck at marketing, so I need all the help I can get. I look forward to chatting with you on Discord, or leave a comment below.

Why this matters

If you would rather not work through this yourself, send me your slowest URL and I will tell you what is actually causing it, for free. You get a written summary of what I find and a fixed-price quote to fix it. WordPress speed optimisation service.

4 comments

  1. Giacomo C. Customer

    I've been a long time reader of WPI's guides, using the "Fastest WP Stack" article as a personal server building bible.
    I've recently taken the plunge and bought Scalability Pro and, even without enabling all the bells and whistles, have seen very noticeable improvements especially with regards to query optimization.

    Awesome work, awesome plugins and this new guide is sure to help even newbies speed up WP websites to a whole different level.

  2. Mike Andrew

    Great post on solving WordPress performance problems! It's crucial to address issues like hosting, theme optimization, caching, and database optimization to boost your website's speed and user experience. I found your insights and suggestions highly valuable.

    I also encourage visitors to take a look at WordPress.com recent post on WordPress performance which was really helpful to me. (https://wordpress.com/forums/topic/page-speed-6/).

    Your website and content are really useful. Keep up the excellent work!

    1. Dave H. Customer

      Thank you for your kind comments. Remember to come and join our performance-obsessed Discord server for more help!

▲
▼
1/1