Purging content from Varnish

Tags: vcl (20) invalidation (2) purge (1)

The most basic and easy-to-use cache invalidation mechanism in Varnish is purging.

The idea is that you can perform a return (purge) in vcl_recv, and Varnish will remove the object. This would free up space in the cache after an object lookup.

This means that the hash of the object is used to identify it, but return (purge) would remove it along with its variants. This isn’t out-of-the-box behavior; you won’t find it in the built-in VCL. You need to write some VCL code for it.

Purge VCL code

Here’s the VCL code you need to implement purging support in your Varnish setup:

vcl 4.1;

acl purge {
    "localhost";
    "192.168.55.0"/24;
}

sub vcl_recv {
    if (req.method == "PURGE") {
        if (client.ip !~ purge) {
            return (synth(405, "Method Not Allowed"));
        }
        return (purge);
    }
}

As you can see, the VCL code starts with an ACL definition. This is very important because you don’t want to expose your purging endpoint to the public. People could get very creative with this, and it could potentially tank your hit rate.

There’s an if-statement in place that checks the ACL and returns an HTTP 405 Method Not Allowed error for unauthorized traffic.

The fact that we choose an HTTP 405 status means we’re not using a regular HTTP GET method. Instead we’re using a custom PURGE method.

If the purger calls the URL using a PURGE method, and the ACL allows the client, we can do a return (purge);

Triggering a purge via HTTP

The VCL logic that purges an object from the cache will be triggered via an HTTP request.

The only requirement is that the PURGE request method is used. Here’s an example:

PURGE / HTTP/1.1
Host: example.com

Since the return (purge) statement does a cache lookup first, it uses the host header and URL to identify the object. This means purging happens on a per-URL and a per-host basis.

In this example the URL is / and the host header is example.com. This means that http://example.com/ will be purged from the cache.

And this is the corresponding HTTP response you may receive:

HTTP/1.1 200 Purged
Date: Tue, 20 Oct 2020 13:30:12 GMT
Server: Varnish
X-Varnish: 32770
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 240
Accept-Ranges: bytes
Connection: keep-alive

<!DOCTYPE html>
<html>
  <head>
    <title>200 Purged</title>
  </head>
  <body>
    <h1>Error 200 Purged</h1>
    <p>Purged</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 32770</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

More examples

If you want to purge the /contact page, you need call the right URL in your purge request:

PURGE /contact HTTP/1.1
Host: example.com

If your Varnish setup allows cached content for the foo.com hostname, the appropriate Host header needs to be added to the purge call:

PURGE /contact HTTP/1.1
Host: foo.com

Integrating purge calls in your application

It is easy to perform a purge on the command line using curl or HTTPie, as illustrated below:

#HTTPie
http PURGE "www.example.com/foo"
# curl
curl -X PURGE "www.example.com/foo"
In reality, you’ll probably use the HTTP client library that comes with your application framework.

For frameworks like WordPress, Drupal, Magento, and many others, there are community-maintained plugins available that perform purge calls to Varnish.