While nginx microcaching already solves page caching (as of static, rarely changing WordPress pages), the performance for dynamically generated pages (like WooCommerce shop pages and admin backend in general) can benefit greatly from additionally using an object cache. Object caching allows an application (in this case WordPress with its plugins, theme, etc.) to store prepared objects (mostly database queries) in a database and quickly retrieve them, therefore improving the performance of dynamic page generation. Object caching is (usually) transparent, which means that it shouldn't be noticeable by users and developers (except for the performance improvements of course).
Currently there are three major object caches available for PHP (and WordPress):
apcu
A PHP caching extension,apcu
can be understood as a successor toapc
, which is basically apc without the opcode caching as it is natively supported since PHP 7.xRedis
A high performance key-value database server (ampng other features) to which PHP can connect to and be used for caching.memcached
Similar to Redis.
To enable WordPress object caching, usually a caching plugin is used. There are caching plugins that do much more than just object caching, like page caching (which would be redundant for Trellis setups or where nginx microcaching is already used), on-site or offloaded image optimizations (which may have been already realized in-theme or by using other, more dedicated plugins) and asset concatenation (which may not be important anymore or even detrimental due to HTTP/2 multiplexing). Therefore a dedicated plugin should be preferred, that just realizes object caching and does it well (and configurable).
This guide uses Redis for object caching, primarily because after some research it was found that it is more stable and on par with apcu
and memcached
performance. If there is interest in using apcu
or memcached
instead or if you have found mistakes in this guide, please feel free to create a new issue on https://github.com/roots/docs/issues in order to further improve this guide.
When you already use Trellis on production for hosting your Bedrock sites, you can add the trellis-redis ansible role to your Trellis ansible setup to easily ensure a local Redis server. Apply the ansible playbook to the server (you may want to test it on a staging server first).
For custom Redis setups, like non-Trellis setups, remote Redis servers/clusters and alike you have to ensure the Redis server is not freely open to the outside world, by limiting its listening range, adding a password, configuring a firewall and so on.
This guide uses the WP Redis plugin to enable WordPress object caching for Redis.
It is a free, OpenSource, fully functional and well maintained plugin (one of its maintainers is the well-known WordPress hoster Pantheon). The plugin uses configuration variables, which makes it ideal for Bedrock sites (that embraces 12 factor app principles) and also supports the wp
CLI tool which many developers already use.
As usual with Bedrock sites, you add the plugin as a composer
dependency to the site's composer.json
.
Either copy the version definition from wpackagist.org or from its GitHub repository and paste it into the site composer.json
(here its latest version 1.1.1
at time of writing is used, also a ^
was prepended to allow for non-breaking updates).
> composer require wpackagist-plugin/wp-redis ^1.1.1
{
"repositories": [
[...]
{
"type": "composer",
"url": "https://wpackagist.org",
"only": ["wpackagist-plugin/*", "wpackagist-theme/*"]
}
[...]
],
[...]
"require": {
[...]
"wpackagist-plugin/wp-redis": "^1.1.1"
[...]
}
[...]
}
Run > composer update
.
As composer.json
:
{
"repositories": [
[...]
{
"url": "https://github.com/pantheon-systems/wp-redis",
"type": "vcs"
}
[...]
],
[...]
"require": {
[...]
"wpackagist-plugin/wp-redis": "^1.1.1"
[...]
}
[...]
}
Run > composer update
.
Deploy the changes and enable the plugin.
The plugin is installed and enabled now and the Redis server runs and is available. What is left to do is some configuration for the plugin to actually connect and make use of the Redis server. Currently the plugin would show a notice in admin backend that it isn't confiured yet to be used.
The WP Redis
plugin we use in this guide uses configuration variables, which is ideal for a Bedrock site.
As usual with Bedrock sites one can define environment-specific configuration by using the appropriate configuration file (config/environments/<environment>.php
).
// Redis cache server (WP Redis plugin)
$_SERVER['CACHE_HOST'] = 'localhost';
$_SERVER['CACHE_PORT'] = 6379;
$_SERVER['CACHE_PASSWORD'] = '';
$_SERVER['WP_CACHE_KEY_SALT'] = 'my-site.com'; // salt to prevent collisions of cached data between different sites
$_SERVER['CACHE_DB'] = 0; // redis DB index, which can be used as additional means of separating cached site data
When you run multiple sites, but also as a general precaution, a non-empty cache key salt should be defined. One of the canonical/primary site domains or some other site-unique name should be used.
Additionally a Redis database index can be set (from 0 to 15, but a much higher limit can be configured for Redis), which can futher help to keep the cached data separated. With the configuration file in place (saved/deployed), the object cache should now be functional and you should notice improvements in site performance.
For the development environment ([...]/development.php
) a different configuration can be used, e.g. a Redis Docker container.
The WP Redis
plugin status and stats can be retrieved using the wp
CLI tool
(you can use aliases like wp @production
; wp @staging
; wp @development
to switch between sites on different environments).
wp redis info
can be used for caching status and statistics.
In practice, significant performance improvements on production/staging (Trellis) and development (WSL 2 + Docker) were experienced for WooCommerce and admin backend. No further adjustments were necessary, object caching was enabled and works fine.
Benchmarks with object caching enabled and disabled and with different caches and configuration for a plain Bedrock site, Sage theme and Trellis server setup could be helpful.
For further improving the performance you may want to use a WordPress profiling plugin like Laps. E.g. there may be the case that, due to a bug, a plugin does a custom, uncached HTTP request on each page request, drastically reducing the performance, even with an object cache. Using profiling can help to track these causes down.
Hi,
Thanks for a great guide, but I can´t make it work. It looks like the php-redis module is not correctly installed, but I don´t get any error messages when ansible installing or provisioning, but when i run phpinfo() I can´t find the module. In wp dashboard I get message "Warning! PHPRedis extension is unavailable, which is required by WP Redis object cache." I use the https://github.com/im-mortal/trellis-redis fork.
Any ideas?