How to Migrate a Discord Bot From Heroku to Fly.io
🔍 WiseChecker

How to Migrate a Discord Bot From Heroku to Fly.io

You have a Discord bot running on Heroku and need to move it to Fly.io because Heroku ended its free tier. The migration involves moving your bot’s code, environment variables, and persistent data to the new platform. This article explains the exact steps to migrate your Discord bot from Heroku to Fly.io, including setting up the Fly.io project, configuring environment variables, and deploying with a Dockerfile or buildpack.

Fly.io is a cloud platform that lets you run full-stack apps close to your users. It offers a free tier with generous limits for small bots. The process requires you to have a Fly.io account, the Fly CLI installed, and your bot’s source code available locally.

This guide covers the entire migration process. You will learn how to prepare your bot for Fly.io, deploy it, and handle common issues like port binding and persistent storage.

Key Takeaways: Migrating Your Discord Bot to Fly.io

  • fly launch command: Creates a new Fly.io app from your bot’s source code and generates a fly.toml config file.
  • fly secrets set command: Transfers environment variables like DISCORD_TOKEN from Heroku to Fly.io securely.
  • fly deploy command: Deploys your bot to Fly.io after configuring the Dockerfile or buildpack.

What Changes When You Move From Heroku to Fly.io

Heroku and Fly.io work differently in several key areas. Heroku used a router that listened on port 80 and 443 and forwarded traffic to your app on a dynamic port. Fly.io requires your app to bind to the port defined in the PORT environment variable, typically 8080 for web services. For a Discord bot that only uses WebSocket connections, you do not need a web server at all. Fly.io still expects your app to bind to a port during deployment checks, so your bot must listen on a port even if it never receives HTTP traffic.

Heroku used Procfile to define process types. Fly.io uses a fly.toml file and optionally a Dockerfile. You can either use a Dockerfile to containerize your bot or rely on Fly.io’s built-in buildpacks that auto-detect your runtime. For most Python or Node.js bots, the buildpack approach works without modifications.

Heroku offered ephemeral filesystem storage. Fly.io provides two options for persistent data: Fly Volumes for database files or object storage like Tigris. If your bot uses SQLite or other local file storage, you must attach a volume to keep data across restarts.

Steps to Migrate Your Discord Bot From Heroku to Fly.io

Follow these steps in order. Ensure you have the Fly CLI installed and authenticated before starting.

  1. Install and authenticate the Fly CLI
    Download the Fly CLI from fly.io/docs/flyctl/install/. Run flyctl auth login in your terminal and follow the browser prompt to log in to your Fly.io account.
  2. Prepare your bot’s source code
    Clone your bot’s repository from Heroku to your local machine. Ensure all dependencies are listed in a requirements.txt for Python or package.json for Node.js. Remove any Heroku-specific files like Procfile or heroku.yml if present.
  3. Create a minimal web server for health checks
    Fly.io requires your app to listen on a port. Add a simple HTTP server that returns a 200 status. For Python bots using discord.py, add this code at the end of your main file:
    from aiohttp import web
    app_web = web.Application()
    async def health(request): return web.Response(text="OK")
    app_web.router.add_get('/', health)
    web.run_app(app_web, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

    For Node.js bots, use Express or the built-in http module.
  4. Run fly launch to create the Fly.io app
    Navigate to your bot’s root directory and run flyctl launch. The CLI will detect your runtime, ask for an app name, and generate a fly.toml file. Choose a region close to your Discord server’s location for low latency.
  5. Transfer environment variables from Heroku
    Run flyctl secrets set DISCORD_TOKEN=your_token_here for each secret. Use the same variable names as on Heroku. Common variables include DISCORD_TOKEN, DATABASE_URL, and BOT_PREFIX.
  6. Add persistent storage if needed
    If your bot uses SQLite or stores files locally, create a volume with flyctl volumes create botdata --region iad --size 1. Then modify your fly.toml to mount the volume:
    [[mounts]]
    source = "botdata"
    destination = "/data"

    Update your bot’s code to write data to /data instead of the current directory.
  7. Deploy your bot
    Run flyctl deploy. The CLI builds your app using the detected buildpack or Dockerfile, uploads it, and starts the bot. Watch the logs for errors by running flyctl logs.
  8. Scale the bot to run continuously
    By default, Fly.io apps scale to zero after 5 minutes of inactivity. For a Discord bot, you need it to run 24/7. Set the minimum instance count in fly.toml:
    [vm]
    count = 1

    Then run flyctl deploy again to apply the change.

Common Issues After Migration and How to Fix Them

Bot Goes Offline After a Few Minutes

This happens when Fly.io scales your app to zero. Ensure you set count = 1 in the fly.toml file. Also check that your bot’s WebSocket connection reconnects automatically. Most Discord libraries handle reconnection, but verify your code does not exit after a disconnect.

Bot Does Not Start and Shows “No health checks passed”

Fly.io requires your app to bind to the PORT environment variable. Your bot must listen on 0.0.0.0 and the port provided by Fly.io. Verify that your HTTP server code uses os.environ.get('PORT', 8080). Also check that the server responds within 30 seconds during startup. Increase the health check timeout in fly.toml if needed.

Environment Variables Not Available

Secrets set with flyctl secrets set are not visible in the Fly.io dashboard. Use flyctl secrets list to verify they exist. If you set a variable after deployment, restart the app with flyctl apps restart to apply the change.

Persistent Data Lost After Restart

Your bot must write data to the mounted volume path, not the default working directory. Check that the volume mount destination in fly.toml matches the path your bot uses. For example, if your bot writes to ./data, set destination = "/data" and update your code to use /data.

Fly.io Free Tier vs Heroku Free Tier for Discord Bots

Item Heroku Free Tier (Deprecated) Fly.io Free Tier
Runtime hours 550 hours/month, app sleeps after 30 min idle Always-on with count = 1, no idle sleep
Memory 512 MB RAM 256 MB RAM (shared CPU)
Persistent storage Ephemeral filesystem only 3 GB free volume per app
Custom domain Free with your-app.herokuapp.com Free with your-app.fly.dev
Database options Heroku Postgres (paid add-on) Fly Postgres, SQLite with volumes, Tigris object storage
Deployment method Git push to Heroku remote flyctl deploy from CLI

You now know how to migrate a Discord bot from Heroku to Fly.io. The key steps are adding a health-check web server, setting environment variables with flyctl secrets set, and ensuring persistent data uses a mounted volume. After migration, test your bot by sending commands and checking logs with flyctl logs. For advanced reliability, configure Fly.io auto-redeploy on Git push using GitHub Actions and set up a monitoring service like UptimeRobot to alert you if the bot goes offline.