I have two backends, and I want to conditionally route to one of them. Why isn't it working? I'm hosting with Heroku


Example Scenario:

I have one backend that I want to serve most of my traffic, but I want all urls that have the string “_example_” in them to go to a second backend.

Normal Approach:

If you are trying to conditionally route requests to different origins, normally you would set the backend in Fastly based on your condition. First, add the additional backend by going to Hosts > Backends and clicking the green ‘New’ button. Once you have your backend added, you will want to add a condition. Click on the gear icon next to your backend, and click ‘Conditions’. A modal will pop up, click ‘NEW’ to create the condition, and fill out the following fields:

  • Name: Url matching string "_example_" (your preferred name)
  • Apply If…: req.url ~ "_example_" (your matching condition)

This will tell Varnish to set req.backend as your second backend if your url matches your condition.

Using Heroku:

Because of how Heroku routes its requests, the above approach of adding your second backend in Fastly and then conditionally changing the backend based on the url string will not work. Heroku routes requests based on the Host header. In the above example, the Host header would still be set to the first backend. So, Varnish would set req.backend to the second backend, but Heroku would get the request and send it to the first backend based on the Host header. Because of this behavior with Heroku, you will want to configure your settings differently than the above example. You will only need one backend, but you will change the Host header instead.

To accomplish this, you will want to create two header rules under Content > Headers, one for each backend. Fill out the fields for each backend like this:

  • Type: request
  • Action: set
  • Destination: http.Host
  • Source: backend_one.herokuapp.com

Your resulting VCL will look like this in vcl_rec (I have omitted lines that were not applicable to this example):

  # default conditions
  set req.backend = heroku_backend;

# Header rewrite Backend1 Host : 10

      set req.http.Host = "backend_one.herokuapp.com";

  # end default conditions

  # Request Condition: matching string "_example_"  Prio: 1
  if( req.url ~ "_example_" ) {

  # Header rewrite Backend2 Host : 10

        set req.http.Host = "backend_two.herokuapp.com";

  #end condition