Geo-steering with IBM Code Engine and Cloud Internet Services

In this post, I want to share a small tip from how I run Machine Learning for Kids: how I run instances of the site in different regions, and use geo-steering so that users are directed to the instance of the site nearest to them.

Using multiple regions for reliability and resilience

I started by following the Code Engine docs for “Deploying an app across multiple regions“.

In that example, they run two instances of their app: one in the US, one in the EU.

They send all traffic to the US app instance, and if a redirect doesn’t work, they send that request to the EU instance as a fall-back.

That does work. But I didn’t like that as an approach.

It has a very noticeable impact on the responsiveness of your site for users who aren’t in the US to send all your traffic to an instance hosted in Dallas.

Plus, using the EU instance of the app as a hot stand-by in this way means that, most of the time, it would never get any traffic, which feels like a waste of resources. [1]

Using multiple regions for responsiveness and usability

I want to run my site in multiple regions, and I want to use all of them. I don’t want a fall-back region, I want to send traffic to every instance of the app.

More importantly, I know that it makes my site noticeably more responsive to send users to an instance of the app hosted near to them, and I want those usability and performance benefits.

To do this, I did things slightly differently to the approach described in the official docs. I’ll describe it here in case you think it might be useful for your app.

The full gorpy detail for how I run Machine Learning for Kids is in GitHub but a simplified version looks like this:

I run three instances of each of the microservices that make up the Machine Learning for Kids site:

  • one in the US
  • one in Europe
  • one in Australia

I added an “IP geolocation header” Page Rule to all of the site subdomains. (For more details about how to do this, see the docs on “Using page rules“.)

This adds a new request header to incoming requests: cf-ipcountry (For more details about this header, see the Cloudflare docs on “HTTP request headers“).

The header is a two-character code for the country that the user is in. I’m using this to decide which instance of the site to send the user to.

I could have just mapped each country code to the nearest instance of the app to that country, but that felt like it would’ve been a pain to maintain. I’ll likely want to change the number of instances of the app in future.

(For example, at the moment I’m sending traffic from Middle East and African countries to the instance in the European region, but I want to be able to add a fourth instance of the app for those countries – without needing to make changes to the mappings for dozens of countries).

Instead, I’ve mapped each of the country codes that I could get in the cf-ipcountry header to the Cloudflare region that the country is in.
(You can see these in countries.json.)

Then I’ve mapped each Cloudflare region to one of my Code Engine projects.
(You can see these in regions.json.)

This means if I decide to run a new instance of the app for one of these regions, it will make it super easy to direct traffic from a Cloudflare region to it.

You can see what it looks like to combine this with the edge function shown in the official docs in my edge-functions.js file.

Notice that I’m still keeping the reliability benefits from the official approach – if the redirect to the nearest instance fails because of an outage in that region, I still want to be able to fall back to another region.

For more info

If you’d like to know more about how the Machine Learning for Kids site is deployed, have a look at the page on GitHub, or please feel free to ask me. Most of it is fairly specific and unique to my site, but I thought this aspect in particular was worth sharing.

[1] – To be fair, you could set the min-instances to 0 and let it scale to zero. But when your primary instance is unavailable, I wouldn’t want to be waiting for my fall-back region to spin up – so I’m not a fan of that, either.


Comments are closed.