I am caching the product details page on Varnish, and then I purge the cache from the backend server whenever the product is updated. I want my clients to never cache this page on their side, but always ask from Varnish, so that I can serve them the most recent copy.
Currently, I have the below config for vcl_backend_response:
sub vcl_backend_response {
unset beresp.http.Set-Cookie;
#unset beresp.http.Cache-Control;
#set beresp.http.Cache-Control = "no-cache";
if (bereq.url ~ "^/products/\d+/details") {
set beresp.ttl = 1h;
}
}
But, using this config, client caches the response for 1 hour, and does not ask again, even the cache is purged on Varnish.
If I uncomment the cache-control related lines, this time Varnish does not cache the page and always asks for a fresh copy from the backend server.
Is this achievable in Varnish v6.0?
Yes, it's possible:
vcl_backend_response
.vcl_deliver
.So clients (browsers) can be instructed to cache with a different TTL than Varnish. The following will ensure that browsers will not cache response:
sub vcl_deliver {
set resp.http.Pragma = "no-cache";
set resp.http.Expires = "-1";
set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
}
Moreover, if you can modify your app, you can resort to a much finer approach outlined in first solution here, that is sending a single Cache-Control
header which defines caching TTL for shared caches (Varnish) and private caches (browser) differently:
Cache-Control: s-maxage=31536000, max-age=86400
The header above will instruct a browser to cache resource for 86400 seconds, while Varnish will cache for 31536000. This is because s-maxage only applies to shared caches. Varnish evaluates it, while browsers don’t.