Varnish 6.x — stale-if-error implementation
The only real solution to implement both stale-if-error
and stale-while-revalidate
is by using vmod_stale
in Varnish Enterprise.
Here's a stale-while-revalidate
implementation in regular VCL, but it doesn't have the flexibility to set stale-while-revalidate
via the Cache-Control
header:
vcl 4.1;
import std;
backend default {
.host="localhost";
.port="8080";
.probe={
.url="/";
}
}
sub vcl_recv {
if (std.healthy(req.backend_hint)) {
set req.grace = 10s;
}
}
sub vcl_backend_response {
set beresp.http.sie = std.integer(regsub(beresp.http.Cache-Control,"^.*stale-if-error=([0-9]+).*$","\1"),0);
set beresp.grace = std.duration(beresp.http.sie + "s",beresp.grace);
}
This example sets grace to whatever the value of Cache-Control: stale-if-error=...
is. In vcl_recv
we can limit this value if the server is healthy, but the grace value is hardcoded and cannot come from Cache-Control: stale-while-revalidate=...
.
beresp.keep
won't work in this case, because it is only used to keep the object around for synchronous revalidation, whereas grace can be used to serve stale data.
The reason why we developed vmod_stale
is to re-arm objects and set new TTL, grace & keep values. By initially setting the keep value to an very high number, we ensure that the object is kept around, and vmod_stale
can then re-arm it.
Your options are to either use my poor man's stale-if-error
implementation, or upgrade to Varnish Enterprise.
Sidenote about Varnish Enterprise
One easy way to try out Varnish Enterprise without upfront licensing payments, if you’re interested, is to spin up an instance on cloud infrastructure:
- Varnish Enterprise on AWS
- Varnish Enterprise on Azure
- Varnish Enterprise on GCP