Solving WordPress Performance Problems

For five years I’ve been solving WordPress performance problems. There are many patterns that exist out there that you can use to help you identify where slow bottlenecks on your site are coming from.

Below, I try to impart that knowledge to help you get the speed you deserve from the hosting you’re paying for.

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

Page generation speed

Scanning your site with GTMetrix can be useful to help identify potential areas where you could optimise speed – particularly on the ‘Mobile’ tab where they simulate devices with less CPU power. Those tools are useful to help you identify when too much is going on in your pages for smart phones to handle.

GT Metrix provides useful pointers to reducing the payload of your site (how big your pages are and how long they take to load in the browser)

These tools will have told you to minify your CSS, compress or resize your images, remove blocking javascript and join javascript files together to make them quicker to download. A lot of these recommendations are out of date with the advent of HTTP/2, but still – running a scan can’t harm and often they provide some useful insights. If you wish to take advantage of HTTP/2, upgrade your hosting or add a CDN in front of your website that supports HTTP/2.

Speed-testing tools like GT Metrix or Pingdom can’t see the activity that’s happening on your server. If you still have a slow site, it’s because you have a large page generation time.

Having a slow page generation time is not just a performance issue, it’s also a scalability issue. If your server takes 4 whole seconds to generate a page, it’s not likely your server is sitting chilling. It’s doing multiple things at the fastest it possibly can. The resource bottlenecks tend to be CPU and disk, so if you see low CPU on your server but long page loads then you probably have slow disks or plugins or theme functionality that is reading too much data from disk.

If your pages generate in 4 seconds rather than 0.5 seconds, that’s 8 times more server resource being consumed. You can pretty much know that if you reduce your page generation time by this much that you will be able to handle 8 times more traffic. That means faster pages for users, but it also means more pages indexable by search engines.

To be able to view the page generation speed on every page of your site, and to identify the sources of performance problems, install the free Query Monitor plugin by John Blackbourn.

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 page caches which is pointless and wasteful of disk resource – with multiple page caching plugins enabled, all pages will be written multiple times to disk yet only one of these cache files will ever be used. Page caching is often the first thing people add to their WordPress site when things get slow.

Page caches are great for helping reduce server load and survive traffic spikes, but they don’t help improve page generation speed.

For page caching, the best option is to use server-based caching e.g. Nginx fastcgi-cache, Litespeed cache or some page-caching system offered by your hosting company or a CDN. These will always be faster and more efficient than any WordPress page-caching plugin. If your hosts don’t 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 you can use WP-Rocket, W3 Total Cache, or a myriad of other page caching plugins. Page caching is trivial to code, so there’s not much they can do wrong.

Your page caching plugin should be able to selectively wipe page cache entries when posts or products are updated, rather than wiping the entire page cache and it should be able to interface with Apache, Nginx or Litespeed to have the web server bypass PHP when there’s a cached file 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 when generating the page. An object cache lets these objects be stored in memory across multiple pages, meaning that the more your site gets browsed the faster it gets.

Object caches really need to be stored in memory to get the most benefit and Redis and Memcached are the two most popular caches that work with WordPress.

WordPress plugins are getting better at using the object cache properly, so get Redis installed onto your hosting (most hosting offers it) and then add the free Redis Cache plugin by Till Kruss or the W3 Total Cache plugin.

Enabling the object cache in W3 Total Cache is easy – select the method to Redis, then tick the box to enable

With your object cache enabled, move from page to page on your site and you’ll see the number of queries used per page dropping and your page generation speed reducing.

See our stack building guide to ensure your hosting provides you with an in-memory Redis cache. You don’t want or need Redis to be writing to disk – it will make it slower.

Many people are using WP Rocket and think that it includes an object cache but it doesn’t. If you are using WP Rocket, you should add the Redis Cache plugin too. They complement each other well.

Hosting Choices

What matters most from your hosting company is the stack they provide you and options to clone your site and create dev/staging areas to try out new things. Then it’s down to whether they provided managed or self managed services, remote backups and the level of support they provide. Here are the key essentials you need:

  • SSD disks (not HDD)
  • 1GB ethernet (not 100Mbps)
  • PHP 7+ (not PHP 5.6)
  • MariaDB or PerconaDB or MySQL 8 (not MySQL 5.6)
  • Redis in-memory mode (for your object cache) or Memcached
  • Nginx scales better than Apache, but this is less relevant than the other items above, Litespeed is also good
  • A page caching system of some kind
  • An HTTP accelerator page cacher- it could be varnish, or nginx fastcgi_cache or some other accelerator. Cloudflare can also help here or MaxCDN too.
  • A CDN – like Cloudflare or MaxCDN. Use their features to compress and minify your CSS and to change browser expiry dates for static files to a year from now.

Generally, if you follow the WordPress Speed Up group and Advanced WordPress groups on Facebook, people tend to prefer Gridpane, RunCloud, Cloudways, Siteground and WP Engine. 

I personally love Digital Ocean – with them I can create new server clones in a minute, and I get full control over my 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 or wherever you like and get amazing performance for very little money.

Upgrading your current hosting

Obviously it would be easier to stay with your current hosts, so here’s a priority list for you:

  1. Upgrade PHP. PHP 7+ is 3x faster than PHP5.6.
  2. Add an object cache – Redis or Memcached.
  3. Upgrade to MySQL 8 or MariaDB.
  4. Add a CDN.

If after all that, your speed is acceptable, then it’s ok to stay with your current hosts.

Cloning your server

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

Cloning your server should be easy and is needed to fully optimise your server – ask your hosts

Ask your hosts if they can create a staging server for you (also called a clone). Most hosts should be able to clone your site for you to a different subdomain so you can experiment with various WordPress settings including activating and deactivating plugins when you’re optimising performance.

The first step in optimising your WordPress site is to find out where the problems lie, and the fastest way to do that is to be able to activate and deactivate various features of your site without affecting your users.

If your hosts don’t provide cloning, there are a few plugins which can clone smaller sites but if you have a larger site you can follow my migration guide to see step-by-step instructions to creating a WordPress clone.

Measuring your page generation time with Query Monitor

The free Query Monitor plugin by John Blackbourn will show you your page generation time, how many MySQL queries ran to generate this page and how much time that took. If you subtract the MySQL time from the total page generation time then you have your PHP time.

Query Monitor is one of my favourite tools – great for quickly discovering potential issues

This helps you know if your slowness is coming from your database, or from the way some plugins are coded which is typically indicated by high PHP time.

Note that the page generation speed you’re seeing is the page generation speed for the current user level. If you are viewing pages as admin then this will be the slowest account. Admins have extra code loaded, can see invisible posts, can use page editors and more, so Admins always have a slower page generation speed than your visitors and customers.

Enable the Query Monitor authentication cookie to see page generation speeds for other users

To view page generation speed as it would be for your visitors (without page caching), you can enable the Query Monitor authentication cookie and then log out of your site.

Optimising your own site

Start with the Query Monitor plugin – look for high query counts, slow queries and queries that return a lot of rows. Experiment on your dev/staging clone (ask your hosts for one!) by deactivating plugins which show high numbers in the above.

Test your pages with Redis disabled first, and then test again with Redis enabled.

Once you’ve found bad plugins, you can either find alternatives or disable their functionality where they’re not needed using the Asset Cleanup plugin. You’ll find Asset Cleanup in the WordPress repository.

The Asset Cleanup plugin lets you deactivate plugins completely on pages where they are not required

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

Finding plugins with too many SQL queries

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

Queries by Component in Query Monitor can be used to find query counts per plugin. Try with Redis disabled to get a clearer picture.

You may find that as your WordPress website gets larger, the number of queries per page increases. In Query Monitor, view Queries by Component to see which plugins are causing your high query count. High query counts typically don’t have a high total database time, but they do typically incur a high PHP time because of the objects being built.

If you’re using WooCommerce shortcodes or filters then you’ll probably be seeing a very high query count in Query Monitor on your slow pages. If the high query counts are coming from your shop filters or on-sale pages, you should use my Faster Woo Widgets plugin.

Recent reviews of my Faster Woo Widgets plugin

If you’re using a page builder like VS Composer, WP Bakery, Elementor or any of the others then they may have inserted the WooCommerce shortcodes for you, or they may even be built into your theme options.

Object caching can help reduce the number of queries in many cases, so try that first if you have a high query count from particular plugins. Otherwise you should test how much page speed boost you get when you deactivate the plugin.

If you have many variations and these are causing a high query count, adding an object cache will help quite a bit as these objects can be re-used on product detail and product archive pages. On top of that, frequently I see shops using variations when they could use simpler product rules or product addons.

Finding plugins with slow SQL queries

Click Queries to view all queries, then click the Time column to sort by time.

Many plugins perform slow SQL queries because they have not been written to use database indexes. An index, when used by SQL queries perform 1000s of times faster than table scans.

I created the plugin Scalability Pro specifically to solve and eliminate table scans in WordPress and WooCommerce. It does this by adding good indexes to tables and rewriting some queries to ensure they use the indexes.

Recent reviews of Scalability Pro

If you have found slow queries, Query Monitor will tell you the plugin causing this. If you find a slow query that object caching or Scalability Pro don’t optimise, let me know and I’ll 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 which cause 100s or 1000s of rows to be fetched when there are only 10 items on the page typically cause high CPU and high RAM usage. Sometimes, an object cache will help reduce the CPU usage but your RAM usage will probably remain high. These plugins are often the ones which fetch the entire database and then process that with PHP to produce stuff on your page.

Plugins with high rowcounts should often just be avoided. Find a replacement.

Speeding up CSS, JS and page rendering speed

If you’re keen to get high Pingdom or GT Metrix scores, you’ll need to optimise your CSS and JS. We don’t focus too much on that ourselves, we believe what matters is user perceived speed. However, in many cases the rules provided by GT Metrix et al to optimise your site help improve perceived speed.

There are a variety of asset optimisation plugins you can use to help get you better Pingdom scores but the best approach would be to use a CDN which provides image, CSS and JS optimisation. Many CDNs also offer page caching meaning you can keep even more load off your WordPress server.

Before optimising CSS and JS, you should first check if that CSS or JS actually needs to be loaded at all. If it doesn’t, disable it with the Asset Cleanup plugin.

Speeding up slow imports

If you have slow imports, my Scalability Pro plugin will help a LOT, especially once your store or imports get larger, but you should also check out my article on the WordPress image sizes problem.

All of the plugins you’ve installed over time, many of them have registered new image sizes and they don’t delete them when you deactivate them. It’s not uncommon for websites to have 30 image sizes registered. That means, when you import something, the image for it will be resized into 30 different sizes and stored in your uploads folder. That’s a lot of extra CPU for resizing and a lot of disk for storing the images.

Fix the image sizes for your site using my guide above and use our Scalability Pro plugin for 10-fold+ speed boosts on large imports. Scalability Pro speeds up imports by deferring term counts until the import has completed and speeding up wp_postmeta lookups which import tools use to check if they should update or insert an item. Check our reviews to see for yourself.

For the ultimate in import speed, eliminate images from your site altogether with our 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 definitely surprise you (lol?). The fastest sitemap plugin is actually 3 years old and no longer maintained. The case study includes techniques to optimise your sitemap generation by 250-fold!

Making sitemaps use an index brings tremendous speed boosts

If your sitemaps are taking over a minute to generate, this will affect other users using your site at the same time so it’s important to optimise. Worse than that, search engine bots like Googlebot have a limited amount of time allocated to index each website so having a slow sitemap means fewer of your website pages will be indexed and available in search engine results.

Speeding up wp-admin

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

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

If you are bulk editing items in wp-admin then it will be difficult to use Query Monitor to help you isolate your issue since these bulk edits happen one at a time using Ajax. So if you want to speed up bulk edits, you should perform a single product edit to see the per-item performance profile and optimise that.

Speeding up your wp_options table

Some options are loaded every page, in rarer cases the entire wp_options table is fetched. Plugins leave these options behind and often they are 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 you decent speed boosts on EVERY page.

W3 Total Cache gives an option to stop storing transients in the database. This reduces database writes.

Check out my Knowledge Base article on managing your wp_options table.

Getting more help

For five years I’ve been coding plugins that optimise WordPress in some way. I’ve written lots of guides to help you in various scenarios, and I’ve personally optimised dozens of previously unoptimisable websites.

Three months ago, I finally started our Discord server and it has been a game changer in terms of providing support and really driving development forward. I want to make performance and scalability easy and available for everyone so read my articles, browse the knowledge base, but if you can’t find what you need or you just want some personalised help then you can find me – Dave Hilditch – on our Discord server almost every day!

The welcome message on our WP Intense Discord server

If you like what I’m doing, please share my articles wildly. I’m great at performance optimisation but I suck at marketing, so I need all the help I can get!

I look forward to chatting to you on Discord, or leave a comment below.

Talk to me