Using Varnish Cache with WordPress

Using Varnish Cache with WordPress

Varnish Cache is a power Caching proxy that you can use to help mitigate large amounts of traffic from hitting your http server (typically Apache, Lighttpd, or others). What Varnish does is keeps a cached copy of a URL in memory when it’s loaded, and then the next person to request that page, will receive the cached copy. You can set Varnish to then expire the page in cache after any amount of time you deem necessary.

For a little more about Varnish you can view their ‘About‘ section.

Where most people have an issue is setting up a good ‘VCL’ or Varnish Configuration Language. To me it looks like a mixture of PERL, C, and some custom formatting but overall, it can be confusing at times. Well, I’ve spent A LOT of time trying to configure Varnish to work with WordPress and today, I think I’ve finally done it. This configuration includes not caching wp-admin, when cookies are set, and if the person is viewing on a mobile or smartphone the hash key is set differently so that plugins like WPTouch will still work.

If you have changes or improvements let me know! The basics were taken from GitHub user mattiasgeniar in his list of Varnish 3.0 Examples

Using Varnish Cache with WordPress

backend default {
.host = “”;
.port = “8080”;
# Called after a document has been successfully retrieved from the backend.
sub vcl_fetch {
set req.http.X-Forwarded-For = client.ip;

# Uncomment this if you want to block certain user agents
#if (req.http.user-agent ~ “yandex” || req.http.user-agent ~ “Yandex” || req.http.user-agent ~ “Baidu” || req.http.user-agent ~ “baidu” || req.http.user-agent ~ “Baidubot” || req.http.user-agent ~ “baidubot”) {
# error 403 “Forbidden, naughty naughty bot.”;

# Get Device type (for caching hashes)
call detect_device;

# Add a www if there isn’t one so we only cache 1 version for www and non-www
if ( !~ “www.”) {
set = regsub(, “$”,”www.$”);

# Uncomment to make the default cache “time to live” is 5 minutes, handy
# but it may cache stale pages unless purged. (TODO)
# By default Varnish will use the headers sent to it by Apache (the backend server)
# to figure out the correct TTL.
# WP Super Cache sends a TTL of 3 seconds, set in wp-content/cache/.htaccess

set beresp.ttl = 24h;

# Strip cookies for static files and set a long cache expiry time.
if (req.url ~ “.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$”) {
unset beresp.http.set-cookie;
set beresp.ttl = 24h;

# If WordPress cookies found then page is not cacheable
if (req.http.Cookie ~”(wp-postpass|wordpress_logged_in|comment_author_)”) {
# set beresp.cacheable = false;#versions less than 3
#beresp.ttl>0 is cacheable so 0 will not be cached
set beresp.ttl = 0s;
} else {
# set beresp.cacheable = true;
set beresp.ttl=24h;#cache for 24hrs

# Varnish determined the object was not cacheable
#if ttl is not > 0 seconds then it is cachebale
if (!beresp.ttl > 0s) {
set beresp.http.X-Cacheable = “NO:Not Cacheable”;
} else if ( req.http.Cookie ~”(wp-postpass|wordpress_logged_in|comment_author_)” ) {
# You don’t wish to cache content for logged in users
set beresp.http.X-Cacheable = “NO:Got Session”;
return(hit_for_pass); #previously just pass but changed in v3+
} else if ( beresp.http.Cache-Control ~ “private”) {
# You are respecting the Cache-Control=private header from the backend
set beresp.http.X-Cacheable = “NO:Cache-Control=private”;
} else if ( beresp.ttl < 1s ) { # You are extending the lifetime of the object artificially set beresp.ttl = 300s; set beresp.grace = 300s; set beresp.http.X-Cacheable = “YES:Forced”; } else { # Varnish determined the object was cacheable set beresp.http.X-Cacheable = “YES”; } if (beresp.status == 404 || beresp.status >= 500) {
set beresp.ttl = 0s;

# Deliver the content

sub vcl_hash {
# Each cached page has to be identified by a key that unlocks it.
# Add the browser cookie only if a WordPress cookie found.
if ( req.http.Cookie ~”(wp-postpass|wordpress_logged_in|comment_author_)” ) {
#set req.hash += req.http.Cookie;

# And then add the device to the hash (if its a mobile device)
if (req.http.X-Device ~ “smart” || req.http.X-Device ~ “other”) {

# Deliver
sub vcl_deliver {
# Uncomment these lines to remove these headers once you’ve finished setting up Varnish.
remove resp.http.X-Varnish;
remove resp.http.Via;
remove resp.http.Age;
remove resp.http.X-Powered-By;…