For sites wanting fine-grained control over how their responses are represented in their edge cache, Pantheon Advanced Page Cache is the golden ticket. Here’s a high-level overview of how the plugin works: When a response is generated, the plugin uses surrogate keys based on WordPress’ main WP_Query
PricingFree downloadThe WordPress.org download is free. Pro versions, add-ons or external services may cost extra.
CompatibilityRequires WordPress 6.4 and PHP 7.4.
SourceWordPress plugins · Nov 10, 2026
01 / Source details
Aboutthistool.
For sites wanting fine-grained control over how their responses are represented in their edge cache, Pantheon Advanced Page Cache is the golden ticket. Here’s a high-level overview of how the plugin works:
01When a response is generated, the plugin uses surrogate keys based on WordPress’ main WP_Query object to “tag” the response with identifers for the data used in the response. See the “Adding Custom Keys” section for including your own surrogate keys.
02When WordPress data is modified, the plugin triggers a purge request for the data’s corresponding surrogate keys.
Because of its surrogate key technology, Pantheon Advanced Page Cache empowers WordPress sites with a significantly more accurate cache purge mechanism, and generally higher cache hit rate. It even works with the WordPress REST API.
Go forth and make awesome! And, once you’ve built something great, send us feature requests (or bug reports) .
How It Works
Pantheon Advanced Page Cache makes heavy use of surrogate keys, which enable responses to be “tagged” with identifiers that can then later be used in purge requests. For instance, a home page response might include the Surrogate-Key header with these keys:
Surrogate-Key: front home post-43 user-4 post-41 post-9 post-7 post-1 user-1
Similarly, a GET requests to /wp-json/wp/v2/posts might include the Surrogate-Key header with these keys:
Because cached responses include metadata describing the data therein, surrogate keys enable more flexible purging behavior like:
When a post is updated, clear the cache for the post’s URL, the homepage, any index view the post appears on, and any REST API endpoints the post is present in.
When an author changes their name, clear the cache for the author’s archive and any post they’ve authored.
There is a limit to the number of surrogate keys in a response, so we’ve optimized them based on a user’s expectation of a normal WordPress site. See the “Emitted Keys” section for full details on which keys are included, and the “Adding Custom Keys” section following for information on how to add your own.
Adding Custom Keys
By default, Pantheon Advanced Page Cache generates surrogate keys based on an interpretation of the main WP_Query query object. Because WordPress sends headers before the page is rendered, you need to use the pantheon_wp_main_query_surrogate_keys filter to include additional surrogate keys for any data present on the page.
For example, to include surrogate keys for a sidebar rendered on the homepage, you can filter the keys using the is_home() template tag:
/** * Add surrogate key for the featured content sidebar rendered on the homepage. */ add_filter( 'pantheon_wp_main_query_surrogate_keys', function( $keys ){ if ( is_home() ) { $keys[] = 'sidebar-home-featured'; } return $keys; });
Then, when sidebars are updated, you can use the pantheon_wp_clear_edge_keys() helper function to emit a purge event specific to the surrogate key:
/** * Trigger a purge event for the featured content sidebar when widgets are updated. */ add_action( 'update_option_sidebars_widgets', function() { pantheon_wp_clear_edge_keys( array( 'sidebar-home-featured' ) ); });
Similarly, to include surrogate keys for posts queried on the homepage, you can pre-fetch the posts before the page is rendered:
/** * An example of pre-fetching a WP_Query to tag the * response with queried data. You'd use `papcx_wp_query()` * a second time within your template to use the data. */ add_filter( 'pantheon_wp_main_query_surrogate_keys', function( $keys ) { if ( is_home() ) { $query = papcx_wp_query( array( 'post_type' => 'page', ) ); foreach( $query->posts as $post ) { $keys[] = 'post-' . $post->ID; } } return $keys; }); /** * Register a 'papc-non-persistent' cache group to cache data * in a non-persistent manner. We only want data in this group * to be cached within the page request. */ add_action( 'init', function(){ wp_cache_add_non_persistent_groups( array( 'papc-non-persistent' ) ); }); /** * Helper function to instantiate a WP_Query object only * once per page request. * * @param array $args Arguments to pass to WP_Query. * @return WP_Query */ function papcx_wp_query( $args = array() ) { $cache_key = md5( serialize( $args ) ); // WP_Query object will be in cache the second time we use the function. $cache_value = wp_cache_get( $cache_key, 'papc-non-persistent' ); if ( false !== $cache_value ) { return $cache_value; } $query = new WP_Query( $args ); wp_cache_set( $cache_key, $query, 'papc-non-persistent' ); return $query; }
Because Pantheon Advanced Page Cache already handles WordPress post purge events, there’s no additional call to pantheon_wp_clear_edge_keys() .
Lastly, the pantheon_wp_rest_api_surrogate_keys filter lets you filter surrogate keys present in a REST API response.
Additional purging by path
When a post is published for the first time, the permalink’s path is also purged even if it has no matching keys. This can be further filtered with the pantheon_clear_post_path filter.
add_action('pantheon_clear_post_path', function($paths) { // Add or remove paths from $paths return $paths }, 10, 3);
Need a bit more power? In addition to pantheon_wp_clear_edge_keys() , there are two additional helper functions you can use:
pantheon_wp_clear_edge_paths( $paths = array() ) – Purge cache for one or more paths.
pantheon_wp_clear_edge_all() – Warning! With great power comes great responsibility. Purge the entire cache, but do so wisely.
Ignoring Specific Post Types
By default, Pantheon Advanced Page Cache is pretty aggressive in how it clears its surrogate keys. Specifically, any time wp_insert_post is called (which can include any time a post of any type is added or updated, even private post types), it will purge a variety of keys including home , front , 404 and feed . To bypass or override this behavior, since 1.5.0 we have a filter allowing an array of post types to ignore to be passed before those caches are purged. By default, the revision post type is ignored, but others can be added:
/** * Add a custom post type to the ignored post types. * * @param array $ignored_post_types The array of ignored post types. * @return array */ function filter_ignored_posts( $ignored_post_types ) { $ignored_post_types[] = 'my-post-type'; // Ignore my-post-type from cache purges. return $ignored_post_types; } add_filter( 'pantheon_purge_post_type_ignored', 'filter_ignored_posts' );
This will prevent the cache from being purged if the given post type is updated.
Setting the Cache Max Age with a filter
The cache max age setting is controlled by the Pantheon Page Cache admin page. As of 2.0.0, there are three cache age options by default — 1 week, 1 month, 1 year. Pantheon Advanced Page Cache automatically purges the cache of updated and related posts and pages, but you might want to override the cache max age value and set it programmatically. In this case, you can use the pantheon_cache_default_max_age filter added in Pantheon MU plugin 1.4.0+ . For example:
When the cache max age is filtered in this way, the admin option is disabled and a notice is displayed.
Updating the cache max age based on nonces
Nonces created on the front-end, often used to secure forms and other data, have a lifetime, and if the cache max age is longer than the nonce lifetime, the nonce may expire before the cache does. To avoid this, you can use the pantheon_cache_nonce_lifetime action to set the pantheon_cache_default_max_age to less than the nonce lifetime. For example:
do_action( 'pantheon_cache_nonce_lifetime' );
It’s important to wrap your do_action in the appropriate conditionals to ensure that the action is only called when necessary and not filtering the cache max age in cases when it’s not necessary. This might mean only running on certain pages or in certain contexts in your code.
WP-CLI Commands
This plugin implements a variety of WP-CLI commands. All commands are grouped into the wp pantheon cache namespace.
$ wp help pantheon cache NAME wp pantheon cache DESCRIPTION Manage the Pantheon Advanced Page Cache. SYNOPSIS wp pantheon cache <command> SUBCOMMANDS purge-all Purge the entire page cache. purge-key Purge one or more surrogate keys from cache. purge-path Purge one or more paths from cache.
Use wp help pantheon cache <command> to learn more about each command.
Debugging
By default, Pantheon’s infrastructure strips out the Surrogate-Key response header before responses are served to clients. The contents of this header can be viewed as Surrogate-Key-Raw by adding on a debugging header to the request.
A direct way of inspecting headers is with curl -I . This command will make a request and show just the response headers. Adding -H "Pantheon-Debug:1" will result in Surrogate-Key-Raw being included in the response headers. The complete command looks like this:
curl -IH "Pantheon-Debug:1" https://scalewp.io/
Piping to grep will filter the output down to just the Surrogate-Key-Raw header:
FinderPress Media Auditor helps site administrators scan for broken images, missing Media Library files, unreachable media URLs, and other media issues across WordPress content. Use it to audit images, video, audio, PDFs, featured images, and attachment files without sending scan data to an external
The Accepted Payment Methods plugin is a straightforward, lightweight solution that enhances your website by displaying visually appealing icons of the payment methods you accept. This plugin is ideal for a variety of websites, including e-commerce platforms, service-oriented websites, and informati