Skip to main content

Page caching with Batcache and Cloudflare

In this lesson you will learn how to install and configure the Batcache plugin for WordPress. You'll hack through the advanced-cache.php file to make edge caching possible with Cloudflare, and you'll also configure cache status logging, to make sure you can accurately measure cache hit rates and response times.

Note this lesson covers the Batcache page caching plugin for WordPress. If you're looking for an alternative, check out the Surge page caching lesson.

Batcache

Batcache is a full-page caching plugin for WordPress, originally developed for the WordPress.com network. It uses a persistent object cache to store the cache data. This is usually paired with a Memcached backend, but works just fine with Redis and other backends as well.

Despite its simplicity (only about 700 lines of code), and given the nature of many persistent object cache implementations, Batcache is suitable for decoupled and multi-server environments, where your cache services run separately from your web server. This gives it a strong advantage over local file-based solutions, such as WP Super Cache or Surge.

Installation

Batcache is not one of those plugins you can easily install and activate with a couple of WP-CLI commands or by clicking around in your WordPress dashboard. You will need to download the drop-in, symlink it manually, and enable it using your wp-config.php file.

Despite being available on WordPress.org, the most up-to-date version still lives on GitHub. Luckily, GitHub is one of the few supported sources for WP-CLI plugin downloads:

cd /sites/uncached.org/public_html
wp plugin install https://github.com/Automattic/batcache/archive/refs/heads/master.zip

You can even "activate" the plugin:

wp plugin activate batcache

However what that activates is the helper plugin called the Batcache Manager, which provides a couple of functions developers can use to invalidate cache for posts and URLs. It also hooks these functions to invalidate caches when a new post is published or an existing one is updated.

To activate the caching plugin itself, you must symlink the page caching drop-in to the wp-content directory:

cd /sites/uncached.org/public_html/wp-content
ln -s plugins/batcache/advanced-cache.php advanced-cache.php

As well as enable it in your wp-config.php file:

define( 'WP_CACHE', true );

After activation, Batcache appends cache information to every HTML response for anonymous visitors, for example:

<!--
    generated 1 seconds ago
    generated in 0.023 seconds
    served from batcache in 0.000 seconds
    expires in 299 seconds
-->

Batcache is typically configured by editing the settings inside the advanced-cache.php file. However, it also supports predefining the $batcache global array. A clean approach is to create a separate batcache-config.php file if your changes are minimal.

<?php
global $batcache;
$batcache = [
    'ttl' => 600,
    'times' => 1,
];

Then load it early on from wp-config.php:

define( 'WP_CACHE', true );
require_once __DIR__ . '/batcache-config.php';

You can find all the available settings in the batcache class in the source code. For more advanced customizations, you will often need to resort to editing the drop-in file directly.

Cloudflare integration

These steps are entirely optional, but as you'll see in the upcoming benchmarks, they make a huge difference, especially if your audience is scattered across different regions.

Batcache itself doesn't have great filters or events we can use to integrate with Cloudflare. It is still possible if you're willing to get your hands a little dirty, and update the drop-in file directly. There are a few things we need:

  1. Ensure a correct Cache-Control header is being sent by Batcache.
  2. Make sure Nginx serves the correct Cache-Control header for static assets.
  3. Change our Cloudflare zone settings to respect the Cache-Control headers.

Batcache

Batcache already sends a Cache-Control header, which is derived from the TTL setting and the expiration time of the cached request. This is usually okay for a single-tier cache, but we typically don't want Cloudflare to cache our dynamic requests for 300 seconds or longer, unless we have a simple way to invalidate that cache.

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.