November 29, 2013
2 min read time

404 handling in Varnish Cache

when you have lots and lots of data, it’s hard to update it in a timely manner. Sometimes all you need is a bit of time while the systems in place are updating. A typical situation is the one where you have two backends serving the same data. However, one of them might lag behind the other one. When a request comes in to the one that is lagging it will throw a 404 Not Found.

The solution is simple to describe; when you get a 404 try the other server. As with most other things implementing it is relatively simple if you know how to do it. Here is how:

Define a director

We'll start off by defining a director "content", with two backends, alfa and beta.

backend alfa {
  .host = “alfa”;
}

backend beta {
  .host = “beta”;
}

director content random {
  {
  .backend = alfa;
  }
  {
   .backend = beta;
  }
}

Then we need to point the requests at this director in vcl_recv. Just "set req.backend = content" should do the trick.

Now we’ve setup Varnish to balance between our two hosts, alfa and beta. Next step, make it try the other one on a 404.

Saint mode

To do this we’ll use saint mode. Saint mode, named after the most  graceful being we could think of is sort of grace mode +. What it does is actually very simple. It maintains a temporary blacklist of backend and objects. So, you can use it to bar Varnish Cache from fetching a certain URL from a certain server. Which, when you think about it is exactly what we want. We want to block Varnish from fetching something from a server for a certain time, maybe 5 seconds. Then to forget about the whole thing.

The VCL

in vcl_fetch:

if (beresp.status == 404) {
   set beresp.saintmode = 5s;
   return (restart);
}

There isn't much to explain, really. We enable saintmode on the object and restart.

saintmode_threshold

saintmode_threshold is a parameter which will influence the how the probes interact with saint mode. If there are more than saintmode_threshold objects on the blacklist for a certain backend that backend will be considered sick. The default is 10. For 404 handling you probably want to disable the whole thing. You can do this by setting saintmode_threshold to 0.

Note: Saint mode has been removed from Varnish Cache 4.0. When I get around to it I can see if I can come up with a recipe for doing this with Varnish 4.0.