Migrating Your Discord Bot From Replit, Heroku or Railway
A step-by-step plan for moving a Discord bot off Replit, Heroku, Railway or Render — inventory, data export, environment variables, cutover and cleanup.
On this page
Plenty of bots start on a general-purpose platform — Replit, Heroku, Railway, Render — and move once the limits start to bite: idle sleeping, keep-alive hacks, usage-based bills that are hard to predict, or resources that don’t fit a long-running bot. Migrating sounds daunting, but for most bots it takes well under an hour. This guide gives you a plan that avoids downtime and duplicate responses.
Why bots outgrow general-purpose platforms
These platforms are excellent at what they were designed for, which is mostly web applications. Bots have different needs:
- A bot must run continuously. Services that sleep when they receive no HTTP traffic disconnect your bot from Discord’s gateway. That’s why so many Replit bots include a tiny web server and an external pinger — a workaround, not a solution.
- Free tiers change. Heroku removed its free dynos in November 2022, and other platforms have adjusted free allowances over time.
- Usage-based pricing is great for spiky web traffic, but a bot that runs 24/7 pays for every hour.
- Ephemeral filesystems. Some platforms reset local files on every deploy or restart, so SQLite databases and JSON files quietly disappear.
A host built for long-running processes removes all four problems. More background is in free PaaS platforms vs dedicated bot hosting.
Step 1: Take an inventory
Before touching anything, write down what your bot depends on. You’ll need:
| Item | Where to find it |
|---|---|
| Runtime and version | package.json engines, .python-version, runtime.txt, or the platform’s settings |
| Start command | Procfile (e.g. worker: node index.js), .replit run = line, or platform settings |
| Environment variables | Platform dashboard → Secrets / Config Vars / Variables |
| Data files | SQLite files, JSON “databases”, uploaded assets |
| External database | Heroku Postgres, Replit DB, Railway Postgres or MySQL, a third-party database |
| Scheduled jobs | Heroku Scheduler, cron add-ons, platform cron |
| Webhooks or dashboards | Any HTTP endpoint the bot exposes |
Copy the environment variable names and values somewhere safe and private. You’ll recreate them on the new host.
Step 2: Clean up platform-specific code
Most bots have a little platform glue worth removing:
- Keep-alive servers. The Flask
keep_alive()file or Express “ping” server exists only to stop the platform sleeping. On an always-on host, delete it and cancel the external pinger. - Replit DB. Replit’s key-value database only works on Replit. Export it (below) and move to SQLite or MySQL.
- Hard-coded paths. Replace paths like
/home/runner/...with paths relative to your project. - Platform environment names. Code that checks for platform-specific variables (like
REPL_ID) to decide behaviour should use your own variable instead, such asNODE_ENV=production.
Make sure dependencies are complete: every package in package.json or requirements.txt. Replit in particular sometimes installs packages automatically on import, which hides missing entries until you deploy elsewhere.
Step 3: Export your data
Heroku, Railway or Render PostgreSQL
pg_dump "$OLD_DATABASE_URL" --no-owner --no-acl -Fc -f bot.dump
pg_restore --no-owner --no-acl -d "$NEW_DATABASE_URL" bot.dump
MySQL
mysqldump --single-transaction -h old-host -u user -p botdb > bot.sql
mysql -h new-host -u user -p botdb < bot.sql
Migrating a database with mysqldump and pg_dump covers flags and pitfalls in detail. Every Kerit Cloud plan includes a MySQL database (paid plans also offer PostgreSQL), and the team can handle a database migration for you if you open a ticket.
Replit DB
Write a short script that runs on Replit and dumps every key to a JSON file, then download it:
import json
from replit import db
with open("export.json", "w") as f:
json.dump({k: db[k] for k in db.keys()}, f)
On the new host, import the JSON into SQLite or MySQL with a one-off script.
Files
Download SQLite databases and any data files while the bot is stopped, so you don’t copy a file mid-write.
Step 4: Set up the new server
On Kerit Cloud:
- Create a server on the free tier or a Discord bot plan, choosing the same runtime version you used before.
- Link your GitHub repository for push-to-deploy, or upload your files via the file manager or SFTP.
- Recreate every environment variable in the panel.
- Set the start command — the part after
worker:in your Procfile is usually exactly right. - Upload data files (SQLite databases, JSON) to the same relative paths.
Don’t start it yet if the old bot is still running.
Step 5: Cut over without duplicates
If both copies run with the same token, both connect to Discord and your bot answers every command twice — or they fight over interactions and fail with “already acknowledged”. Cut over in this order:
- Stop the bot on the old platform.
- Take the final data export (so no writes are lost).
- Import the data on the new host.
- Start the bot on the new host and watch the console for the ready line.
- Test your main commands in a server.
The gap is usually a minute or two. For bots where even that matters, schedule the switch during your quietest hour.
Step 6: Move scheduled jobs
Heroku Scheduler and similar add-ons don’t come with you. Either move the schedule into the bot itself (a setInterval, node-cron, or discord.ext.tasks loop) or, on a VPS, use cron. Schedules inside the bot should store their state so a restart doesn’t skip or repeat a run — see cron jobs and scheduled tasks.
Step 7: Clean up
Once the bot has run happily for a day or two:
- Delete the old deployment so it can’t start accidentally.
- Remove old environment variables from the platform, and rotate any secrets that were stored there if you’re closing the account.
- Cancel the external uptime pinger if you only used it as a keep-alive — or repoint it at a proper health check.
- Update your README with the new deploy process.
Common migration problems
The bot runs but data is missing. The data export happened before the old bot stopped, or files were uploaded to the wrong path. Check paths relative to your working directory.
Cannot find module or ModuleNotFoundError. A dependency the old platform installed automatically isn’t in your dependency file.
Different behaviour on a different Node or Python version. Match the version you used before, then upgrade deliberately later.
It answers twice. The old copy is still running somewhere. Stop it and reset the token if you can’t find it.
Summary
Migrating a bot is mostly bookkeeping: list the runtime, start command, environment variables and data; remove keep-alive hacks and platform-specific storage; export your database and files; recreate the setup on the new host; then stop the old bot before starting the new one. With a bit of preparation, the whole move takes minutes, and the result is a bot that stays online without workarounds.