June 14, 2021
3 min read time

Two-minute Tech Tuesdays - Dynamic Backends


In this episode we'll be looking at dynamic backends. Dynamic backends in Varnish allow backends to be defined on the fly, instead of being predefined. Basically imagine if instead of connecting varnish to one specific origin server, you enable it to connect to different ones as required, say multiple servers.



Traditionally backends in Varnish are defined in the VCL file using a static backend definition. Host and port information is also static, and any DNS name that is used will be resolved at compile time:


backend default {
   .host = "server1.example.com";
   .port = "80";


The same applies when using multiple backends, to perform load balancing. The association between the backend and the director object in charge of load balancing is also done statically. 

This approach has some limitations. Because DNS is resolved at compile time, any runtime changes in terms of DNS are not noted by Varnish. If your IP address changes while Varnish is running, it will not know. Also, a hostname can only have a single IP address. If your hostname uses multiple IP addresses for DNS-based load balancing, that is out of the question. And lastly, it is not possible to define ad-hoc backends using runtime information.

And that's exactly why dynamic backends come into play, through Varnish Enterprise’s goto VMOD you can define them, and they offer some clear benefits. 

First of all, you can use DNS records with multiple IP addresses and perform DNS-based load balancing. If DNS records tend to change every now and then, that is also supported. So if you have a dynamic inventory, potentially in the cloud, VMOD goto is the perfect module for you. 

And finally, you can define backends at runtime and use all kinds of input to locate the backend. Here's a code example that shows you how to get started with DNS-based load balancing:


import goto; {
    backend default none;
sub vcl_init {
new apipool = goto.dns_director ("backend.example.com"); }
sub vcl_recv {
set req.backend_init = apipool.backend();


You import the goto VMOD, you still have to define the static backend, but in this case, it's an empty one. And then you initialize the director object through goto.dns_director. Instead of defining it statically, whatever IP address is linked to backend.example.com is used, and can be refreshed.

If multiple IP addresses are used, the director object will cycle through them, every time you call APIpool.backend.

Here's another code example where we define an ad-hoc backend:


import goto; 
backend default none;
sub vcl_backend_fetch {
set bereq.backend = goto.dns_backend (bereq.http.host);


We can do that using goto.DNS_backend and whatever hostname is entered will be resolved. It could use runtime variables, or could even use a string. Whatever hostname is returned will be resolved to its IP address. If multiple IP addresses are used, we will cycle through them.