Skip to main content
Illustration by Annie Ruygt of a bird carrying an app to a balloon who is welcoming the app to join his group This guide will walk you through migrating your Heroku app to Fly.io. Just follow the steps in order. What this guide covers:
  • Web apps in any language (Node.js, Python, Ruby, Go, etc.)
  • Postgres databases
  • Redis
  • Background workers
  • Environment variables
  • Custom domains
Time required: Most apps can be migrated in under 30 minutes. Unlike Heroku’s dyno-based tiers, Fly.io uses pay-as-you-go pricing - you only pay for the compute, storage, and bandwidth you actually use. There are no fixed plan tiers to choose from. See fly.io/pricing for current rates.

TL;DR - The Fast Path

For experienced developers, here’s the entire migration in 7 commands:
For a more detailed explanation, read on.

Prerequisites

Install both CLIs:

Step 1: Export Your Heroku Configuration

First, let’s capture everything about your Heroku app.
Take note of:
  • Your add-ons (Postgres, Redis, etc.)
  • Your dyno types (web, worker, etc.)

Step 2: Prepare Your App

Make sure you have your app’s source code locally:

Check for a Dockerfile

Fly works best with a Dockerfile. If you don’t have one, that’s fine - fly launch will generate one for you based on your app type.

Check your Procfile

Your Heroku Procfile maps directly to Fly processes. A typical Procfile:

Step 3: Launch on Fly

From your app directory:
This will:
  1. Detect your app type (Node, Python, Rails, etc.)
  2. Generate a Dockerfile if needed
  3. Create a fly.toml configuration file
  4. Ask if you want to provision a Postgres database
When prompted:
  • Choose a name for your app (or accept the generated one)
  • Select your preferred region
  • Say Yes to Postgres if you need a database (choose “Managed Postgres” for the fully-managed option)
  • Say No to deploy now - we’ll do that after setting up secrets

Step 4: Set Up Your Database

If you have Heroku Postgres, create a Managed Postgres cluster on Fly:
Save the connection details it outputs! You’ll see something like:
Note the cluster ID (the CLUSTER_ID part) - you’ll need it for the next few commands. If you lose it, you can always find it with fly mpg list. To import your data, use fly mpg proxy to create a local tunnel, then pg_dump and psql:
You’ll see some errors about Heroku-specific extensions (pg_stat_statements, event triggers) - these are safe to ignore. Your actual data will import successfully. Attach the database to your app:
This automatically sets DATABASE_URL as a secret on your app.

Step 5: Set Up Redis (if needed)

If you use Heroku Redis or Redis Cloud:
Follow the prompts. This uses Upstash Redis which is fully managed. After creation, attach it to your app:
Note: Fly Redis doesn’t support importing existing data. For most use cases (caching, sessions), this is fine - the cache will warm up naturally.

Step 6: Import Environment Variables

Remember that heroku-env.txt file we created? Let’s import it:
Double-check that secrets were imported:

Step 7: Configure Processes (Web + Workers)

If your app has multiple process types (web + worker), edit your fly.toml:
For a release command (like database migrations), add:

Step 8: Deploy

Watch the deployment. If something fails, check the logs:

Step 9: Verify Your App

Step 10: Migrate Your Domain

If you have a custom domain on Heroku:
Update your DNS:
  • For apex domains (example.com): Create an A record pointing to the IPv4 address
  • For subdomains (www.example.com): Create a CNAME pointing to your-app-name.fly.dev
Once DNS propagates, Fly automatically provisions an SSL certificate.

Quick Reference: Command Mapping

Common Add-on Replacements

Multiple Environments (Staging/Production)

Fly doesn’t have “pipelines” like Heroku. Instead, create separate apps:
For CI/CD, use GitHub Actions with the Fly GitHub Action.

Shutting Down Heroku

Once everything is working on Fly:
  1. Update your DNS to point to Fly
  2. Wait for DNS propagation (check with dig yourdomain.com)
  3. Monitor both apps for a day to ensure no traffic goes to Heroku
  4. Scale down Heroku dynos: heroku ps:scale web=0 worker=0 -a $HEROKU_APP
  5. Cancel Heroku add-ons
  6. Delete the Heroku app: heroku apps:destroy -a $HEROKU_APP

Getting Help