Cache tags + Varnish

Last updated on
8 February 2017

Varnish Cache is a web application accelerator also known as a caching HTTP reverse proxy. Varnish is used on thousands of Drupal sites to speed up page load performance by a factor of 10-1000x, and it can be used with cache tags to make cache invalidation easy.

For basic cache tag integration, you need to do three things to make sure Varnish works well with the cache tags generated by Drupal:

  1. Update your Varnish VCL so it handles BAN requests properly
  2. Send a cache tags header (e.g. X-Cache-Tags) header with every request, containing a space-separated list of all the page's cache tags.
  3. Send a BAN request with the appropriate cache tags whenever content or configuration is updated that should expire pages with the associated cache tags.

Note: Some of the information on this page is subject to change pending #2692523: Generate own Purge-Cache-Tags header.

Update Varnish VCL

The Symphony FOSHttpCache bundle includes some excellent documentation on VCL changes required for cache tag support, but here are the minimum required VCL changes to get started (for Varnish 4.x):

Inside vcl_recv:

sub vcl_recv {
    ...
    # Only allow BAN requests from IP addresses in the 'purge' ACL.
    if (req.method == "BAN") {
        # Same ACL check as above:
        if (!client.ip ~ purge) {
            return (synth(403, "Not allowed."));
        }

        # Logic for the ban, using the X-Cache-Tags header.
        if (req.http.X-Cache-Tags) {
            ban("obj.http.X-Cache-Tags ~ " + req.http.X-Cache-Tags);
        }
        else {
            return (synth(403, "X-Cache-Tags header missing."));
        }

        # Throw a synthetic page so the request won't go to the backend.
        return (synth(200, "Ban added."));
    }
}

Inside vcl_backend_response:

sub vcl_backend_response {
    # Set ban-lurker friendly custom headers.
    set beresp.http.X-Url = bereq.url;
    set beresp.http.X-Host = bereq.http.host;
    ...
}

Inside vcl_deliver:

sub vcl_deliver {
    # Remove ban-lurker friendly custom headers when delivering to client.
    unset resp.http.X-Url;
    unset resp.http.X-Host;
    # Comment these for easier Drupal cache tag debugging in development.
    unset resp.http.X-Cache-Tags;
    unset resp.http.X-Cache-Contexts;
    ...
}

Make sure you restart Varnish after making the appropriate VCL changes!

Send a cache tags header

Drupal's Purge module automatically configures the Purge-Cache-Tags header for every page, so once you enable Purge, that header will be sent.

Send a BAN request when content or configuration changes

Using the Generic HTTP Purger module, you can go to the Purge configuration page (admin/config/development/performance/purge) and add an HTTP Purger.

Enter your Varnish server details (hostname, port, path, etc.), and under the 'Headers' configuration, enter a header with the following configuration:

  • Header: X-Cache-Tags
  • Value: [invalidation:expression]

Once you save this purger configuration and configure a cron job to process the Purge queue (drush p-queue-work), Varnish should start banning pages as soon as the purge queue triggers the bans!

Some of the notes in this documentation were adapted from the following sources: