Ten lessons learned about Varnish, the old fashioned way.

1. Varnish needs to run on 64 bit.

2. Cache two versions of each request, the gzip compressed and non-gzip compressed one. i.e. don’t send a gzip response to a browser that wanted an uncompressed response.

3. Don’t cache 403 responses, let the backend (Apache/express) answer those.

4. Detect bots and devices, mobile/tablet/desktop, at the Varnish level as delivery rules change there. Then pass the results to the backend. E.g. a header that basically says “spam bot”, “desktop”, or “mobile”.

5. Pass the X-Forwarded-For header to the backend so it can log requests. Otherwise you’ll just see requests in the logs from or another internal address that Varnish is coming from. One cannot do much analytics on that data!

6. Build a cache warmer. Here’s an illustration where example.com is your Varnish'd site and cache-warmer.txt is a list of paths that should be loaded. The idea is to put these items in cache if they’re not already there. Running the warmer a second time will hit those items in cache and it should finish quickly!

var _ = require('underscore');
var fs = require('fs');
var request = require('request');
var count = 0;
_.each(fs.readFileSync(__dirname + "/cache-warmer.txt").toString().split("\n"), function(line){
    (function(line) {
        request.get("http://example.com" + line, function(e, r, body) {           
            if(_.isUndefined(r)) {
                console.log('cannot fetch');
            else {
                console.log(++count + ': ' + line + ' ' + r.statusCode);

7. Transform URLs sent to backend/used in cache hashes to fine tune the number of cache hits. For example, http://example.com/?query=blah alongside http://example.com/?query=blah&page=1. When they actually yield the same HTML they should be using the same Varnish key, so rewrite one of them to look like the other. Otherwise memory and response time is wasted on a copy.

8. Cache the requests that are killing the CPU, not the favicon, static images, or CSS. Requests that come directly from the filesystem are easily fulfilled by a web server. Let the backend do its job! Measure success by a reduced load on the server, not in cache hit percentage.

9. Consider the nature of the data you’re caching. In my case it rarely changes and overall the number of cached items is enormous. I chose a longer expiry time on for the cached items (10 days) and to store the cache in file storage versus memory. My particular strategy is “longtail”. That is to say, the cache only starts to prove its worth after a few days. When choosing a longer expiry time just remember to purge those items when the data changes.

10. When making changes to the configuration, you can reload it without dumping current cache, which probably took hours or days to attain. Here’s how to do it:

# varnishadm
varnish> vcl.load refresh /etc/varnish/default.vcl
varnish> vcl.use refresh