Varnish Saint Mode is a lesser known gem inside varnish that lets you serve stale content from cache, even when your backend servers are unavailable.

This article explains how to configure varnish to take advantage of this feature. If you want to follow along, create a directory and add an index.html. I am going to use a poor man's Python web server python -m SimpleHTTPServer to serve this directory.

Here is a simple Varnish config to take advantage of this feature:

# /etc/varnish/default.vcl

backend default {
    .host = "127.0.0.1";
    .port = "8000";
    .saintmode_threshold = 0;
    .probe = { .url = "/"; .interval = 1s; .timeout = 1s;
               .window = 5; .threshold = 3;}
}

sub vcl_recv {
  if (req.backend.healthy) {
    set req.grace = 1h;
    set req.ttl = 5s;
  } else {
    # Accept serving stale object (extend TTL by 6h)
    set req.grace = 6h;
  }
}

sub vcl_fetch {
  # keep all objects for 6h beyond their TTL
  set beresp.grace = 6h;

  # If we fetch a 500, serve stale content instead
  if (beresp.status == 500 || beresp.status == 502 || beresp.status == 503) {
    set beresp.saintmode = 30s;
    return(restart);
  }
}

The following scenario will let you test the saint mode:

  • Kick-off the Python web server in the directory you created with python -m SimpleHTTPServer. Note: Every 1s varnish is going to probe your backend to determine if it is healthy.
Serving HTTP on 0.0.0.0 port 8000 ... 
127.0.0.1 - - [17/Feb/2014 11:51:02] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [17/Feb/2014 11:51:02] "GET / HTTP/1.1" 200 -
  • Fetch the index.html you created earlier through Varnish
$ curl -I http://127.0.0.1:6081
HTTP/1.1 200 OK
Server: SimpleHTTP/0.6 Python/2.7.5+
Content-type: text/html
Last-Modified: Mon, 17 Feb 2014 10:19:03 GMT
Content-Length: 146
Accept-Ranges: bytes
Date: Mon, 17 Feb 2014 10:53:07 GMT
X-Varnish: 976346109
Age: 0
Via: 1.1 varnish
Connection: keep-alive
  • Now kill the Python web server process and confirm it is down
$ curl -I http://127.0.0.1:8000
curl: (7) Failed connect to 127.0.0.1:8000; Connection refused
  • Fetch index.html through Varnish again
$ curl -I http://127.0.0.1:6081
HTTP/1.1 200 OK
Server: SimpleHTTP/0.6 Python/2.7.5+
Content-type: text/html
Last-Modified: Mon, 17 Feb 2014 10:19:03 GMT
Content-Length: 146
Accept-Ranges: bytes
Date: Mon, 17 Feb 2014 10:55:14 GMT
X-Varnish: 976346113 976346109
Age: 127
Via: 1.1 varnish
Connection: keep-alive

Note the Age: 127 header. This tells you the number of seconds since Varnish fetched this page from your web server.

Congratulations, you're now serving pages without your webserver! Varnish's saint mode can be a nice safety net when the unexpected (but inevitable) happens and buy you some time to get things back into working order.