Migrating Rails Application to Another Heroku Region

I recently had to migrate a Rails application hosted on Heroku from US-East to EU-West. Heroku provides some decent documentation on the process here but I ran into a few gotchas and I thought I’d share my experience.

Here’s a little background. In general I use Heroku to deploy most of my web applications. Heroku is a platform as a service (PaaS) provider hosted on Amazon EC2. While I am experimenting with provisioning my own EC2 instances and leveraging Amazon RDS for running a Postgres database, for now Heroku is my primary choice for hosting web applications. Why?

  • I can deploy my apps in seconds with the Heroku CLI.
  • I mostly build Ruby apps and Heroku is optimised for Ruby.
  • My dev-ops commitment is minimised so I can focus on building features.
  • The vast majority of my apps work happily on the free tier.
  • The new dyno types will allow me to implement background processing on the free tier.
  • I may need more control over a hosting environment in the future, but for now, Heroku does me just fine.

So why the need to move AWS region? Well, by default, when you deploy an application to Heroku it automatically assigns it to the US-East region unless you explicitly specify the –region eu flag. I wasn’t concerned about this at first, until it came to integrating S3 file storage. My application users are primarily based in Ireland and the UK so when setting up an S3 bucket I obviously chose EU West so as to minimise latency for my end users. Then it clicked. AWS offer free data transfer out of S3 to EC2 instances within the same region. Heroku runs on EC2. My application does some post processing of images following upload to S3 so there would be some data transfer required. I needed my Heroku deployment to be in EU-West. So here is how I did it.

S3 bucket creation

Creating an S3 bucket

(1) Fork Your Application

Switching regions is not as simple as just toggling a setting on your Heroku dashboard. You must fork a new application from your existing one and place it in the new region. The above command initialises and deploys the new ‘forkedapp’ to the EU region. Once completed you need to make sure all your add-ons are setup correctly. Some will need manual configuration and there’s even the possibility that certain add-ons will fail provisioning if they are not yet available in your area. The only issue I ran into was having to setup my ‘heroku scheduler tasks again. SSL certs also need to be added to the new SSL endpoint and your custom domains switched over if you’re using one.

(2) Database Switchover

Users with production tier database plans can provision a follower DB on their new app and configure it to follow the master DB on the original app. Once the databases are almost in sync you can initialise maintenance mode on the original app, promote the follower to the primary DB for the new app (only once the DBs are fully up to date) and then switch over domain endpoints. This is well documented here.

For users like myself who are on development tier postgres plans, the process is a little different.  heroku pg:backups capture -a existingapp creates a backup of our original ‘existingapp’ database (make sure you’re in maintainance mode while doing this or else you risk losing data on the switchover). We then merge this backup into our new database for ‘forkedapp’. This is the step which primarily caused me issue during the switchover process. The heroku documentation suggests to use the ‘pg:backups’ add-on to restore the data from the original backup to the new database as follows:

This kept telling me that I had not installed the pg:backups add-on. It seems the pg:backups add-on is now deprecated and I was unable to add it using  heroku addons:add pgbackups --app forkedapp  or heroku addons:create pgbackups --app forkedapp . It seems the new backup functionality works through a ‘pg:backups’ namespace, but not through the add-on. The new docs can be found here and appear quite straightforward. At the time I was switching over, however, I never found them for some reason. I used PG copy and it worked a treat. While still in maintenance mode, I fired off:

You can get the ‘EXISTING-DB-COLOR’ and ‘FORKED-DB-COLOR’ values with the  heroku pg:info command targeted at your respective apps. This worked like a charm and copied over my persisted data without a hitch. It’s then simply a matter of taking your app out of maintenance mode unless your custom domains DNS settings, add-ons or SSL certificates need further configuration. Obviously, setting your DNS TTL to a low value well in advance of the changeover is particularly beneficial as it will allow requests to your custom domains to be routes to the ‘forkedapp’ without much delay from the time the new settings are configured.

Let me know if you ran into any other unusual behaviour when migrating an app to a new region. Happy coding!