Search code examples
varnish

Varnish Cache Invalidate by Timestamp


Is there a way to clear varnish cache by timestamp. I want to remove all the caches responses from yesterday or from any specific timestamp.


Solution

  • Although there is an obj.age variable in VCL, it's not accessible from the ban() function in Varnish versions older than 6.2. This currently also includes our 6.0 LTS version.

    Insert timestamp in the cache as response header

    One way to approach this problem is by inserting a timestamp in a custom header at insertion time.

    Here's some example VCL where we assign the current UNIX timestamp to the time response header:

    vcl 4.1;
    import std;
    
    sub vcl_backend_response {
      set beresp.http.time = std.real2integer(std.time2real(now,0),0);
    }
    
    sub vcl_deliver {
      unset resp.http.time;
    }
    

    By assigning this value in sub vcl_backend_response, we're ensuring that this value is stored in the cached object as part of the response headers.

    Matching the timestamp in the ban expression

    Any response header can be matched by the ban() function. But since ban() has no > or < operators, we'll have to use a regular expression.

    When testing, one of my objects had 1636103641 as its timestamp. The current timestamp was 1636103870, which means the object in cache was 229 seconds old.

    I created the following regular expression:

    ^1636103[7-8][0-9]{2}$
    

    This matches all timestamps between 1636103700 and 1636103899, which is a 199 second range, based on the current timestamp.

    By NOT matching this pattern, older timestamps would be selected and that's in fact the trick.

    I ended up using the following ban command to match old objects:

    varnishadm ban obj.http.time '!~ ^1636103[7-8][0-9]{2}$'
    

    Customizing the regex to your needs

    Before banning, make sure the custom header containing the timestamp is added to your VCL code. This custom header will be matched in your ban command.

    Based on your needs, take the current UNIX timestamp, calculate the range you want to match and create a regex that does an inverse match.

    Matching obj.age as of Varnish 6.2

    If you're using Varnish 6.2 or newer, you can simply run the following ban command:

    varnishadm ban obj.age '> 1d'
    

    This will remove all objects that have been in the cache for more than a day.