- New SQL enhancement for Scalability Pro to fix WooCommerce long-running query in the product-hero block - August 31, 2023
- Create a static favicon.ico to avoid surplus PHP requests for rush traffic - July 25, 2023
- Breaking Through WooCommerce Restrictions with Super Speedy Filters: The Power of Pretty Permalinks - May 10, 2023
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?
Table of Contents
- Page generation speed
- Page caching should ideally be handled at server level
- Object caching is essential
- Hosting Choices
- Upgrading your current hosting
- Cloning your server
- Measuring your page generation time with Query Monitor
- Optimising your own site
- Finding plugins with too many SQL queries
- Finding plugins with slow SQL queries
- Finding plugins with high row counts
- Speeding up CSS, JS and page rendering speed
- Speeding up slow imports
- Speeding up slow sitemaps
- Speeding up wp-admin
- Speeding up your wp_options table
- Getting more help
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.
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.
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.
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.
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, Kinsta and WP Engine.
I personally love Digital Ocean and Hetzner – 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.
If you want this ultra performance with a front-end control panel, there’s no-one better than Gridpane. Their stack is an evolution of my stack with a great control panel on top to make building, configuring, cloning, migrating really simple point and click. Gridpane + Hetzner gives ultra performance levels at incredibly cheap prices.
Upgrading your current hosting
Obviously it would be easier to stay with your current hosts, so here’s a priority list for you:
- Upgrade PHP. PHP 7+ is 3x faster than PHP5.6.
- Add an object cache – Redis or Memcached.
- Upgrade to MySQL 8 or MariaDB.
- 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.
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.
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.
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.
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.
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 Super Speedy Filters 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.
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
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.
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!
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.
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!
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.