Purging content from Varnish
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)
;
PURGE
method.The logic that captures the PURGE
request method must be explicitly defined in your VCL code, otherwise the built-in VCL behavior will not recognize the request method and will trigger a return (pipe)
.
Piping will send the request directly to the backend and will abandon any notion of caching and of HTTP. The piped request will be treated as bytes shuffled over the wire. Although the backend may respond with a 200 OK
status, it will not be a confirmation of a successful 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>
return (purge)
uses the vcl_synth
subroutine to return a synthetic HTTP response. If you want to change the output you get from a purge call, you have to override the vcl_synth
subroutine and update the resp.body
variable.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"
For frameworks like WordPress, Drupal, Magento, and many others, there are community-maintained plugins available that perform purge calls to Varnish.