Caching in WordPress
Most managed WordPress hosting providers come with their own caching solutions, often tightly integrated into their systems. The upside is that you don't have to worry about it at all, and it usually works as intended. The downside is that you lose granular control and are locked into one specific, often proprietary, implementation.
The beauty of self-hosting WordPress on your own VPS or dedicated server is the freedom to use any caching plugins you want, along with any additional setup and services they might require.
Caching in WordPress typically refers to page caching. However, there are plenty of other caching layers involved in a typical WordPress request.
Object caching
Object caching allows WordPress core, themes and plugins to store arbitrary data in memory for quick reuse when needed. It is heavily used internally in WordPress core, as well as by most functions and APIs it exposes to plugin and theme developers.
For example, after fetching ten posts from the MySQL/MariaDB database, WordPress will hold each individual post in its object cache. If you reference that same post again, in a widget, footer, or anywhere else on the page, WordPress will use the cached object rather than querying the database again.
The same applies to options, users, navigation menus, widgets, patterns, blocks
and more. This is why it is perfectly safe to call get_option()
as many times
as you like during one request.
In a default WordPress installation, object caching is non-persistent. This means the cache is empty at the beginning of every request. Using plugins and often some additional software, such as Redis or Memcached, the WordPress object cache can be made persistent.
A persistent object cache implementation typically comes in two layers: a slightly slower remote cache (such as Redis or Memcached) and a faster local (PHP) non-persistent layer. Fetching a post becomes an entire journey:
get_post() <- local object cache <- remote object cache <- database
Persistent object caching is generally a worthwhile improvement, especially in a dedicated server setup with plenty of available memory and a local Redis/Memcached instance.
The original object cache implementation lives in the WP_Object_Cache class. This is typically extended by persistent cache implementations. The two most popular are the Redis Object Cache and Memcached Object Cache plugins.
Transient caching
The Transients API is very similar to object caching but with a database-backed persistent layer by default. This is used by WordPress core to cache RSS feeds for that dashboard widget nobody ever uses, as well as core, plugin and theme update data, and a few other things.
Transients make heavy use of object caching. In fact, when persistent object caching is available, the Transients API becomes a mere alias for the object cache API.
Query caching
Fetching posts, pages, products, navigation menus, and even block theme
templates makes use of the WP_Query
APIs, which implement caching for most
types of queries. This
relies
on the object cache APIs under the hood and will greatly benefit from a
persistent object cache implementation.
Query caching sometimes also refers to database query caching at the MySQL level. Both MySQL and MariaDB have caching mechanisms in place, including the now deprecated query_cache, and the InnoDB buffer pool. Some WordPress performance plugins implement their own layer, which I strongly advise against unless you're running a remote database in a different continent.
Page caching
This is one of the more effective caching layers, allowing you to serve the
entire request from cache without having to do any work. In WordPress, this is
implemented at the advanced-cache.php
drop-in layer, which runs very early.
WP Super Cache and
Surge are great free single-purpose
plugins in this area, plus at least a dozen commercial offerings.
However, most modern hosts usually go further with page caching, adding even more layers between the site and the visitor for quicker delivery. For example:
- Nginx's fastcgi_cache delivers the entire request without hitting PHP at all.
- Varnish or Nginx's
proxy_cache
(when used as a reverse proxy) delivers a request without hitting your web server. - Edge caching is a technique allowing the use of a CDN to serve a request without even talking to the datacenter you're hosted at.
Finally, with proper HTTP headers, you can trick your visitor's browser into serving the request from its local browser cache without even having access to the Internet, assuming they've loaded the page before, of course.
PHP Opcache
Not strictly WordPress related, but a very important part of running multiple WordPress sites or plugin-heavy sites. When PHP code is executed, it is first compiled into opcode. Having a cache for these compiled files means PHP can skip the expensive compilation step next time the file is used.
This is usually enabled by default in PHP and offers quite a few configuration options. However, a couple of important default settings are:
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
This is usually more than enough for one site. However, consider the following:
- WordPress core alone has over 1200 individual PHP files
- The Jetpack plugin has 1400+ PHP files
- The most popular SEO plugin has 1250+ PHP files
- The most popular visual builder plugin has 1000+ PHP files
Not all files are used, of course, but with this one WordPress site and three plugins, we're looking at close to 5000 individual PHP files. It doesn't take many more plugins or a $49 theme to hit the 10k limit.
The Opcache lives inside the PHP-FPM master process, which means it's a shared
cache for all configured PHP pools and thus shared among all the sites in our
configuration. You can use opcache_get_status()
to check the current usage.
I recommend raising this to at least 100k in /config/php/php.ini
. The memory
consumption is less of an issue, but we'll add an alert as we approach that in
the Monitoring module.
Linux page cache / disk cache
I normally don't mention this in the context of WordPress caching, as it is quite an advanced concept. However, given that this course is about self-hosting on a VPS or dedicated server, I feel it's an important and often overlooked feature.
This article is for premium members only. One-time payment of $96 unlocks lifetime access to all existing and future content on wpshell.com, and many other perks.