All posts
Engineering

Migrating from Metabase on Heroku to Metabase Cloud using AWS EC2

March 28, 2024

The Problem

My organization wanted to move our self-hosted Metabase instances from Heroku to Metabase Cloud. The catch: Metabase's migration script requires you to be on the latest version first, and our instance was significantly out of date. That dependency turned a simple migration into a multi-step detour.

The Game Plan

The first instinct was to use Heroku buildpacks to upgrade the instance directly on Heroku:

heroku login
cd metabase
 
heroku buildpacks:set https://github.com/metabase/metabase-buildpack -a metabase
git commit --allow-empty -m "Trigger rebuild"
git push heroku master

This got us from v0.41.4 to v0.45.3 — but the latest version at the time was v0.48.8. Worse, Heroku itself was now a dead end:

"Starting with this release, Metabase 0.45 — Heroku support is now deprecated."

Further upgrades on Heroku were no longer possible.

The Revised Game Plan

With Heroku out of the picture, the new approach had three steps:

  1. Back up the Metabase database from Heroku
  2. Restore it into a fresh PostgreSQL container on an EC2 instance running the latest Metabase via Docker
  3. Run Metabase Cloud's migration script against the EC2 instance

Step 1 — Back Up the Heroku Database

# Create a backup of the Metabase instance on Heroku
heroku pg:backups:capture --app metabase-app
 
# Download the backup locally
heroku pg:backups:download --app metabase-app
 
# List all backups for the app
heroku pg:backups --app metabase-app
 
# Get details about a specific backup
heroku pg:backups:info b017 --app metabase-app
 
# --- Extras ---
 
# View the backup schedule
heroku pg:backups:schedules --app metabase-app
 
# Set an automated backup schedule
heroku pg:backups:schedule DATABASE_URL --at '02:00 America/Los_Angeles' --app metabase-app
 
# Restore a specific backup
heroku pg:backups:restore b101 DATABASE_URL --app metabase-app

Step 2 — Set Up PostgreSQL on EC2

SSH into your EC2 instance, then install the Heroku CLI and restore the backup into a Docker-managed Postgres container:

# Install Heroku CLI on EC2
curl https://cli-assets.heroku.com/install.sh | sh
heroku login -i
 
# Copy the Postgres backup from your local machine to EC2
scp metabase-app.dump user@remote_host:/path/to/destination/
 
# Pull and run a Postgres container
docker pull postgres
docker run --name postgres_container -e POSTGRES_PASSWORD=YOUR_PASSWORD -d postgres
 
# Copy the dump file into the container
docker cp metabase-app.dump postgres_container:/
 
# Shell into the container
docker exec -it postgres_container bash
 
# Create the target database and restore
psql -U postgres -c "CREATE DATABASE metabasedb;"
pg_restore -U postgres -d metabasedb -O /metabase-app.dump

Step 3 — Launch Metabase on Docker

Point Metabase at the restored Postgres database:

sudo docker run -d -p 3000:3000 \
  -e "MB_DB_TYPE=postgres" \
  -e "MB_DB_DBNAME=yourdbname" \
  -e "MB_DB_PORT=5432" \
  -e "MB_DB_USER=yourusername" \
  -e "MB_DB_PASS=yourpassword" \
  -e "MB_DB_HOST=yourdbhost" \
  metabase/metabase

The Final Touches

Once the container is running, verify the version by navigating to http://<your-ec2-instance-public-ip>:3000 and going to Settings → Admin. You should see v0.48.x (or whatever the current latest is).

From there, download and run Metabase Cloud's migration script against the EC2 instance. The script handles the rest — and once it's done, you're fully on managed hosting with no more Heroku maintenance to worry about.