Recommendations for altering VCL hash?
Are there any guidelines or best practices to keep in mind if I need to alter the Varnish hash for my service?
-
There are a few things to keep in mind:
If you can avoid altering
vcl_hash
, do so.Vary:
is more often than not a better alternative. The key being that if you have different versions for the same URL, you usually still want to purge them all at once when purging that URL. For more info, see my blog post about Vary.
Make your changes on a test service first, and test thoroughly.Messing up
vcl_hash
can cause the wrong page to be served from cache. This can lead to a lot of confusion amongst users and people dealing with the fall-out.
If you wantpurge all
to work, include#FASTLY hash
in yourvcl_hash
.
For example:perl sub vcl_hash {
FASTLY hash
set req.hash += req.url; return(hash); }
If you do not, purge all will simply do nothing.
(The example above only hasreq.url
and notreq.http.Host
, meaning that theHost:
header is no longer used in making the hash, and thushttp://example.com/foo
andhttp://www.example.com/foo
will be a single object in our cache.)Unless you're doing something really advanced, make sure you at the very least use
req.url
somewhere invcl_hash
, even if only as an argument toregsub()
.For example:
vcl sub vcl_hash {
FASTLY hash
set req.hash += req.http.host; if (req.url ~ "^/api/foo.json\?") { set req.http.temp = "/api/foo.json?" regsub(req.url, "^.?&.$", "\1"); set req.hash += req.http.temp; } else { set req.hash += req.url; } return(hash); }This will make Varnish ignore all query string parameters except
myparam
for URLs that start with/api/foo.json?
. You might do this if you want to leave req.url intact for logging orrestart
purposes.As mentioned earlier, purging is affected, since we purge by the hash. So if you add something to the hash, like say, a header, make sure you account for that header when sending a purge to Fastly. (Or use Surrogate-Key purging)
If you add
set req.hash += req.http.Accept-Encoding
for instance (which Fastly normalizes to be eithergzip
,deflate
, or not present) you would have to send 3 separate purges. One withAccept-Encoding: gzip
, one withAccept-Encoding: deflate
, and one without anyAccept-Encoding
header.
(This is where using theVary:
header really shines. HavingVary: Accept-Encoding
in the responses would allow you to have all 3 variations of an object in the cache, and purge them with a single request.)Make sure to include
return(hash)
. If you do not, the function will fall through to the default VCL built into varnish, which forvcl_hash
will addreq.url
andreq.http.Host
to the hash.Although, if you wanted to, you could write a really short
vcl_hash
function by relying on that. For instance:
vcl sub vcl_hash {
FASTLY hash
set req.hash += req.http.Accept-Encoding; }This function will work just fine. However, we do advise not to rely on implicit things like that, as it might confuse others reading your VCL.
Asvcl_hash
is probably the least overridden VCL function, and the easiest to shoot yourself in the foot with, we strongly advise to use extreme caution. You could, for instance, post your proposedvcl_hash
function on this forum, and get a little peer review.
Please sign in to leave a comment.
Comments
1 comment