Limit traffic load on your application server and go super fast with varnish

Problem

Your application server is always busy, always processing, always fetching data from the database and serving back to your clients. That is exactly what it’s suppose to do but when clients make the same requests over and over again, your application also performs the same calculations again and again.

Solution

Simple! Only process the request using your application server when you have to.

Implementation

We are going to use a simple rails api application as an example. We have a resource /api/designs/:id that returns details of a design object.

Now, if i make this request again, my application server will do exactly the same thing …. fetch the design details from the database, maybe from multiple tables, serialize it, and return. But as long as I know the design object is not changed, there is really no reason for my application server to go through the same process again. That’s when varnish comes to play. Varnish is a web application accelerator also known as a caching HTTP reverse proxy. You install it in front of any server that speaks HTTP and configure it to cache the contents. Go ahead and install varnish from https://www.varnish-cache.org/docs/4.0/installation/index.html#install-index

Let’s go ahead and change the Cache header on our response so that varnish knows to keep a copy.

And the header now looks like

Alright, cool! Now we just need to add our backend to varnish.

Start varnish and make a request to that resource. The first request you make looks like this

Varnish returns a MISS because it does not have a copy of the response, therefore it calls fetch to get it from the backend. When we make the same call again, we will see a HIT instead and varnish will not have to make the same call to the backend to retrieve the result.

The first time we made the request it took 0.018 vs the second time 0.006, making the response way faster but also not having to bother our application server.

Finally, we just need to make sure that varnish does a fetch if the design object changes within the next 24 hours. You can ban urls manually in the varnishadm by

Obviously we would like to do this as the objects change automatically from our app. So let’s add this to the vcl

Varnish is now configured to accept PURGE requests and ban the url that matches the regex in the request’s ‘Ban-Url’ header. Here is a quick implementation to make that request in your ruby app

Once your app makes a PURGE request, varnish will be forced to fetch from your application server.

All you have to do now is use active record’s call backs to detect change in the object and make PURGE request (probably async) with the appropriate Ban-Url.