January 8, 2013
1 min read time

Sub-second TTLs in Varnish Cache

Typically the backend instructs Varnish how long to cache content through the Cache-Control header. The resolution here is relatively coarse - seconds. I'll show you how to create rules for caching with sub-second precision.

The TTL (beresp.ttl, actually) already has subsecond precision. So, we can set the TTL to any decimal value. However, when parsing Cache-Control we adhere to RFC2616 and interpret is an integer. So, in order to have decimal precision we need a way to pass a decimal number to Varnish. 

First things we need is to load the std module. It gives us the duration function which makes it possible to work with, obviously, durations. Now we can just pick the TTL out of a random header and set the TTL. VCL:

import std;
sub vcl_fetch {
   #  Set TTL to whatever x-max-age tells us or 120s
   set beresp.ttl = std.duration(beresp.http.x-max-age + "s", 120s);
}
 
Now, we could enhance this somewhat. I would like it to not be so blunt. This code will override Cache-Control blindly. If some backend objects still would use Cache-Control that would be silly. Also, it would be nice to se the TTL set on an object.
 
import std;
sub vcl_fetch {
   if (beresp.http.x-max-age) {
      set beresp.ttl = std.duration(beresp.http.x-max-age + "s", 120s);
      # Set a response header.
      set beresp.http.x-subsecond-max-age = beresp.ttl;
   }
}

Can we improve this further?