Presslabs Cache Specifications

Cache information can be vital to your site performance. This is an overview of our Presslabs cache system, containing information about cache types, cached pages, expiration times, as well as a quick list of parameters we cache & pass to the back-end.

Our proprietary WordPress caching layer is in place for all our customers, ranging from civic NGO projects that we host for free, to highly demanding enterprise hosting customers. We have in place all the major types of server side caching (page cache, CDN cache, object cache and opcode cache) combined in a geographically distributed network.

Cache layers

As you can see in the location section of your account, your site is served from a geographically distributed network of servers comprising a Kubernetes cluster as the backend node, a cache node and many front-end nodes.

This is because our caching system has 3 layers: front-end nodes, caching nodes and, at the backend level, object cache (memory cache) and opcode cache. Don’t panic, all this “caching” is in place so that your site loads as fast as possible, in order to offer a good user experience. It also ensures that if your site’s backend is down for some reason, your visitors will see it as up and running, as the pages are served from cache. Just don’t hit any “purge the cache” buttons in such situations!

Ok, so how does this all work? When a request is made, it will go to the front-end node that is closest to the user. For example, if the request is made from Australia, it’ll go to our front-end node in Melbourne. If the requested page is found in the front-end node, it will be served to the visitor in no time, with the status of cache: HIT. You can check if a page was served from cache by inspecting the x-presslabs-stats header.

If the requested page was not found here, it’ll go to one of the cache nodes. If the page is found in the cache here, it will be returned to the front-end node, which will deliver it to the user. In this case, the cache status will also be cache: HIT and the response time will still be lightning fast.

Both on the front-ends and on the cache nodes we have both page cache and CDN cache.

If the request is not found here, thus (cache: MISS), the request will reach the back-end of the site, where we have object caching and opcode caching. The object caching is used for storing database queries and we are using Memcached for this purpose. The opcode cache involves compiling and storing the PHP code to RAM, which saves time and computing power.

The expired items (cache: EXPIRED) are collected from our logs and sent to Carbon Cache , a custom tool that handles cache operations such as invalidation and purging.

Cache categories

A WordPress site is made up from various components: posts and pages, taxonomies, tags, the media items, comments and so on. These components have different caching needs, so we’ve split them accordingly in three categories:

  • pages cache - this is the HTML of your blog pages and posts. You can read more about its refresh and expiration time below. Additionally, you can manually purge (flush) the page cache from the Managed Hosting Dashboard
  • CDN cache - contains all the static files (images, etc.); this type of cache is never invalidated, as you normally should have no need to purge it; if you do however - for example if you add or change an image and keep the old url, you can drop us an email at and we’ll purge the CDN cache in no time
  • listing cache - contains the taxonomy archives and the date archives; they are invalidated each time someone publishes or updates a page or post

Additionally, there are 2 categories for the code related files and the memory cache:

  • assets cache - contains code-related files (CSS, JS, image files and other theme related files). This cache category is invalidated at each code update; you can manually purge it from the Managed Hosting Dashboard
  • memcached or memory cache - contains the cached database queries. This can also be flushed from the Managed Hosting Dashboard .

For logged-in users, cache is disabled by default, therefore only the “memory cache” is in place.

Cache refresh and expiration time

The cached pages have different expiration times based on their freshness. By default, they have the following expiry times:

  • articles and pages newer than 2 days: 30 minutes (0.5 x base)
  • articles and pages newer than 30 days: 1 hour (1 x base)
  • articles and pages newer than 365 days: 4 hours (4 x base)
  • older articles and pages: 1 day (24 x base)
  • all other pieces of content: 1 hour

The multipliers cannot be changed, but the base TTL (which is 3600 seconds by default) can be increased by requesting this from our support team.


Please note that the front page, the taxonomy archives and the date archives are invalidated on each post or page publication, or update. When comments are made, deleted, approved, or marked as spam, that particular article is refreshed as well.

You can manually trigger a cache refresh for the Page Cache, Assets Cache and Memory Cache from the Managed Hosting Dashboard . If you purge one type of cache, you won’t be able to hit the button again for the next 5 minutes.

Query parameters

Starting with April 2016 we’re caching all the GET requests, for any resources (even PHP, excluding some key paths like wp-login.php, wp-signup.php, wp-cron.php and xmlrpc.php). In order to make a request more cache-friendly and reliable, we’re stripping down all non-standard WordPress parameters. In other words, these parameters are not passed to the back-end (where php gets executed). This is the list of parameters which we cache and pass to the back-end (WP API specific arguments and WP Query Vars from WordPress Query Vars – Codex ):

  • _ajax_nonce
  • action
  • attachment_id
  • author
  • author_email
  • author_exclude
  • context
  • exclude
  • feed
  • hide_empty
  • karma
  • id
  • include
  • media_type
  • meme_type
  • menu_order
  • offset
  • order
  • orderby
  • p
  • page
  • paged
  • page_id
  • parent
  • parent_exclude
  • per_page
  • post
  • postid
  • relatedposts
  • robots
  • s
  • search
  • slug
  • status
  • type
  • wpmp_switcher
  • wptouch_switch

Besides this list, all filter parameters like filter[*] are also passed to the back-end and cached.

Additionally, you can add custom non-strippable parameters from our dashboard, check the cache section .

Manage absolute TTL for resources

If you have a page or post that needs a special cache refresh policy you can set the X-Accel-Expires header to the value you desire. Here is a sample code snippet where the TTL is set for 5 minutes and the resource is /feed/:

add_action( 'send_headers', 'add_header_x_accel_expires' );
function add_header_x_accel_expires() {
    if ( strpos ( $_SERVER['REQUEST_URI'], '/feed/' ) === 0 ) {
        header( 'X-Accel-Expires: 300'); // number of seconds

You can also exclude pages from cache by setting a header with a 0 TTL for the specific pages where you need the cache to be disabled.

Flush programatically a cached page

It can happen that you might want to flush from the code a specific resource, not by clicking in the Dashboard page , so here is the Presslabs function that can be called:

 * @param  String $url The url to be flushed.
 * @param  bool $refresh Should the cache be warmed up after the invalidation process.
 * @return bool            If the refresh was successfully queued.
function pl_cache_refresh( $url, $refresh = true )


Yes, it is. The cookie names which trigger cache bypassing by default are currently the ones used by Woocommerce: woocommerce_cart_hash, woocommerce_items_in_cart or wp_woocommerce_session_. So to exempt the cart from the cache you can include the woocommerce_items_in_cart coookie.