We all want the fastest site possible and chances are this isn’t the first guide you’ve ever read on WordPress performance. But we’ve noticed a lot of guides skip emcaore technical approaches to performance, and thus miss many easy opportunities to speed up WordPress sites.
Mainly, most WordPress performance guides target the easiest methods instead of the leanest methods.
Are you ready to supercharge your WordPress performance? Great! Let’s amnive in!
What do we mean by lean?
Lean to us means we’re aiming for a small foot print where each performance module is separable and does one job really well.
This means that we are generally anti-caching plugins, as they tend to take an everything-and-the-kitchen-sink approach to solving problems. These plugins definitely have their place, and we won’t judge you if you choose to use them, but we would be remiss if we didn’t share our philosophy.
Minimum Requirements
Most of the strategies in this guide assume you are self-hosting WordPress on a Unix based server with Nginx and PHP-FPM. If that’s not you, or you don’t know what Unix is, this may not be the best guide for you!
WordPress Performance Priorities
When we think about performance, we’re talking about a lot of things that all contribute to the speed a page loads when a browsers requests it.
For simplicity, we will break it down into two categories and prioritize them thusly:
- Server performance
- Browser performance
Server Performance Basics
When a browser requests a page on your site, a few things happen very quickly:
- Nginx or Apache receives a request for a page.
- It routes that request to PHP.
- PHP makes additional calls to your database
- The result is sent to the browser.
There are a few places we can jump in here to improve performance. We can go straight to full page caching, which shortcuts the whole process but it also leaves something crucial out: WordPress Dashboard Performance
The first ingredient in our performance coffee cake is Object Caching.
Object Caching
Object Caching allows WordPress to cache the results of database queries. This is highly useful because for many queries, the results have not changed between subsequent requests. SELECTs from the database on a decent server are fairly cheap, but they add up fast. Caching this data can make dramatic difference in page load, especially on admin pages where full page caching cannot be employed.
For our server stack, we use Redis. Redis, like Memcached and others, stores data in the server’s RAM. This means it can be retrieved at the maximum possible speed.
In our case, we use ServerPilot to manage our stack so installing Redis is very easy .
Once Redis is installed, we use the plugin WP Redis to move the WordPress object cache to Redis.
In about 10 minutes (ok, maybe 30 or 60 if you aren’t using ServerPilot), super high performance object caching is ready to go. See, WordPress performance is easy!
The second ingredient in our performance baclava is Opcaching.
Opcaching
Opcaching allows PHP to compile your PHP files into machine readable byte code. This is much preferred over interpreting the file anew each page load and can greatly speed up your WordPress application.
Starting in PHP 5.5, opcaching is compiled into PHP and does not require any additional modules to be installed or enabled. So if you have PHP 5.5 installed, you’re already benefiting from opcaching unless you explicitly turned it off. (We think you can do that? We don’t know because there’s literally no reason you would want to do that.)
But there’s a catch! Opcaching increases performance, but by default it checks the file on disk for modifications on each and every page load. This eliminates a big benefit of opaching right off the bat.
To maximize performance, we want to tell PHP to execute its cached version /without/ reading the disk (typically the slowest component on a server, even with SSD drives). This can be done with a simple PHP config option :
opcache.validate_timestamps=0
(0 is false, 1 is true)
You can typically configure this through .htaccess
or .user.ini
. (The syntax will be slightly different if you’re using .htaccess
)
Now, this also has a catch. When this is enabled, changes to files will NOT take effect until you clear the opcache. This can be managed easily by using the plugin Opcache Dashboard . It allows you to clear the cache easily. It also automates it during WordPress updates.
The next ingredient in our homemade performance strudel is full page caching.
Full Page Caching
Ok, so now we’re at our frenemy, full page caching. Full page caching is a great way to speed up a site, especially on cheap, shared hosting.
Why frenemies? The main reason we don’t love full page caching is that we have a natural dislike for page caching plugins. This is part prejudice and partly the belief that page caching should be done /before/ PHP handles the request.
Setting aside our unjustifiable prejudices for a moment, we’ll say that we know many WordPress sites that use plugins like W3 Total Cache and WP Rocket and these are very smart and happy people.
But since we’re purists, we’ll give you two additional options:
Option 1: Maybe you don’t need it?
Full page caching is great, but you may not need it. If you don’t have a super high traffic site, and you don’t expect to get featured on Hacker News or whatever the kids are on about these days, you aren’t really going to benefit much day to day.
In fact, if you’re reading this site in March 2017, we don’t currently have it enabled and our site is still what we would term “damn fast”.
Option 2: Nginx FastCGI Caching
Our favorite method of full page caching is using Nginx FastCGI Caching. We prefer it because once you go through the (admittedly a bit difficult) steps to set it up, it’s basically a set it and forget it system.
How does it work? Nginx typically proxies requests to PHP-FPM. But it has the ability to cache the results it gets back from those proxy requests to disk and load subsequent requests from that cache.
Unlike caching plugins, you don’t really have to worry about plugin updates, bug fixes, or the many features of those plugins you probably aren’t using.
We used Mark Jaquith’s gist to set up ours, but we recently saw Delicious Brains cover this topic in more detail. You can read it here. Both of these require Nginx so if you’re on Apache you should probably use a caching plugin.
The other advantage of this setup is that it is by definition faster than a caching plugin can ever be.
Browser Performance Basics
Now that we’ve covered server performance, we’re ready to tackle browser performance, or as I like to call it: How to get yelled at by PageSpeed Insights repeatedly. (But I kid.)
There are a couple of things we can do to improve performance once a browser has downloaded the page from our server.
This is in someways a more complex topic because it covers a wide range of issues, many of which relate to themes and plugins and can consequently be difficult to control.
Instead of diving deep, we’re going to summarize a few places to start:
Image Compression
Most images you upload to your site are not optimized and require the browser to download more bytes than is strictly necessary. This can be dramatic in some cases.
We recommend the plugin WP Smush to automate the compression of new uploads, as well as handle old uploads. (Don’t worry, it’s lossless)
Deferring Scripts and Stylesheets
Deferring scripts and stylesheets after the body allows the browser to process a page without waiting for scripts and stylesheets to download.
This is a double edged sword because there are times we need or at least /want/ a script or stylesheet to load in the header. This is especially true of stylesheets because pages tend to look ugly when the stylesheet is totally deferred.
Without getting into the weeds, we can confidently recommend the highly-rated Autoptimize.
It makes it easy to combine, minify, and defer scripts. It can also help you inline the essential styles your page needs to load correctly and defer the rest. (Check their FAQ!)
What about CDNs?
CDNs distribute your static content from servers near your audience. Our favorite CDN at the moment is Amazon Cloudfront , but MaxCDN is another solid option.
Having a CDN is not a necessity, but it can help visitors who are geographically far way from your server download pages faster.
If you do choose to use a CDN, our favorite plugin to facilitate this is part of Mark Jaquith’s WP Stack. We have a fork of it that fixes a couple of minor issues. Essentially you can place wp-stack-cdn.php in your plugins directory and activate. Then you add this line to wp-config.php:
define(‘WP_STACK_CDN_DOMAIN’, ‘cdn.example.com’);
It has support for environment variables (WP_STAGE
) which allow you to disable the CDN locally while keeping the same codebase.
Summary
Ok, I know what you’re thinking. “How is this a leaner stack??”
That’s a fair point. You may wager that a single, many featured plugin is a better way to solve these WordPress performance concerns. There’s no accounting for taste, and we are not here to suggest our way is superior to all other ways.
We just prefer small, easily separable modules with laser focus on a single feature to large, multi-featured platform plugins.
If you have any questions about the above, drop us a comment. We’ll do our best to point you in the right direction.
chronicrd says
Great article on WordPress Caching !
A client of mine found this very helpful too. Thank you.
LH&R,
-tank
Chronic Research and Development
Ron Shank says
Great post. Thanks. OPCache Dashboard hasn’t been updated in 2 years. Do you know any alternatives. It looks abandoned.