Search code examples
varnish

Varnish not making origin call for infrequently requested cache


I'm noticing this behavior on Varnish 6.5 where it's not making backend calls per the max-age cache control origin response, if the request is not frequently requested by clients.

Below's the expected behavior I see for a cache requested every 1 second. It has 20 seconds max-age cache-control header from origin:

Request 1:
HTTP/2 200
date: Tue, 20 Jul 2021 02:02:02 GMT
content-type: application/json
content-length: 33692
server: Apache/2.4.25 (Debian)
x-ua-compatible: IE=edge;chrome=1
pragma:
cache-control: public, max-age=20
x-varnish: 1183681 1512819
age: 17
via: 1.1 varnish (Varnish/6.5)
vary: Accept-Encoding
x-cache: HIT
accept-ranges: bytes

Request 2:
HTTP/2 200
date: Tue, 20 Jul 2021 02:02:04 GMT
content-type: application/json
content-length: 33692
server: Apache/2.4.25 (Debian)
x-ua-compatible: IE=edge;chrome=1
pragma:
cache-control: public, max-age=20
x-varnish: 891620 1512819
age: 19
via: 1.1 varnish (Varnish/6.5)
vary: Accept-Encoding
x-cache: HIT
accept-ranges: bytes

Request 3:
HTTP/2 200
date: Tue, 20 Jul 2021 02:02:05 GMT
content-type: application/json
content-length: 33692
server: Apache/2.4.25 (Debian)
x-ua-compatible: IE=edge;chrome=1
pragma:
cache-control: public, max-age=20
x-varnish: 1183687 1512819
age: 20
via: 1.1 varnish (Varnish/6.5)
vary: Accept-Encoding
x-cache: HIT
accept-ranges: bytes

Request 4:
HTTP/2 200
date: Tue, 20 Jul 2021 02:02:06 GMT
content-type: application/json
content-length: 33692
server: Apache/2.4.25 (Debian)
x-ua-compatible: IE=edge;chrome=1
pragma:
cache-control: public, max-age=20
x-varnish: 854039 1183688
age: 1
via: 1.1 varnish (Varnish/6.5)
vary: Accept-Encoding
x-cache: HIT
accept-ranges: bytes

You can see the Request #4 above makes a new origin request with the cache request id being 1183688.

Now if I wait a long while and make that same request, the cache age is pretty old and varnish does not make an origin request to cache a fresh object:

Request 5 after a while:
HTTP/2 200
date: Tue, 20 Jul 2021 02:10:08 GMT
content-type: application/json
content-length: 33692
server: Apache/2.4.25 (Debian)
x-ua-compatible: IE=edge;chrome=1
pragma:
cache-control: public, max-age=20
x-varnish: 1512998 1183688
age: 482
via: 1.1 varnish (Varnish/6.5)
vary: Accept-Encoding
x-cache: HIT
accept-ranges: bytes

I suppose I could start adding the Expires header from origin, but looking for explanation why varnish behaves this way if the request is infrequent. Thanks.


Solution

  • TTL header precedence in Varnish

    Varnish does check the max-age directive, but there might be other factors can cause the TTL to be an unexpected value.

    Here's the TTL precedence:

    1. The Cache-Control header's s-maxage directive is checked.
    2. When there's no s-maxage, Varnish will look for max-age to set its TTL.
    3. When there's no Cache-Control header being returned, Varnish will use the Expires header to set its TTL.
    4. When none of the above apply, Varnish will use the default_ttl runtime parameter as the TTL value. Its default value is 120 seconds.
    5. Only then will Varnish enter vcl_backend_response, letting you change the TTL.
    6. Any TTL being set in VCL using set beresp.ttl will get the upper hand, regardless of any other value being set via response headers.

    Your specific situation

    The best way to figure out what's going on is by running varnishlog and adding a filter for the URL you want to track.

    Here's an example for the homepage:

    varnishlog -g request -q "ReqUrl eq '/'"
    

    The output will be extremely verbose, but will contain all the info you need.

    Tags that are of particular interest are:

    Please also have a look at your VCL and check whether or not the TTL is changed by set beresp.ttl =.

    What do I need to help you

    In summary, if you want further assistance, please provide your full VCL, as well as a varnishlog extract for the transactions that is giving you to unexpected behavior.

    Based on that information, we'll have a pretty good idea what's going on.