Migrating a Telegram Bot From Heroku, Railway or Render
Move a Telegram bot from Heroku, Railway or Render without losing updates or sessions — inventory, webhook changes, session files, data export and a clean cutover.
On this page
Telegram bots often begin life on a general-purpose platform and move once the rough edges show: processes that sleep, filesystems that reset on deploy, bills that grow with every hour the bot runs. Moving a Telegram bot has a few specifics compared with other apps — webhooks must be re-pointed, MTProto sessions must come along, and two copies must never poll at once. This guide covers a clean migration.
Why Telegram bots outgrow these platforms
- Sleeping processes. A long-polling bot receives no inbound HTTP traffic, so platforms that suspend idle services put it to sleep — and it stops answering until something wakes it.
- Ephemeral filesystems. Some platforms reset local files on every deploy or restart. Telethon and Pyrogram session files, SQLite databases and downloaded media vanish, and userbots ask to log in again.
- Workarounds. Webhook-only designs and external pingers keep bots awake, but they’re patches over the real problem.
- Unpredictable cost. Usage-based billing is great for bursty web apps; a bot running 24/7 pays for every hour.
A host built for persistent processes fixes all of these. On Kerit Cloud’s Telegram hosting, processes never sleep, disks are persistent NVMe, and both polling and webhooks work on every plan.
Step 1: Inventory your bot
Write down, from the old platform:
- Runtime and version — Python, Node.js or Java, and the exact version.
- Start command — from the
Procfile(worker: python bot.py),railway.json,render.yamlor dashboard settings. - Environment variables — every name and value, including
BOT_TOKEN, database URLs, API keys, andTG_API_ID/TG_API_HASH/session strings for MTProto clients. - Update mode — polling or webhook. If webhook, note the current URL (
getWebhookInfoshows it). - Data — the database (managed Postgres, MySQL, Redis) and any files: SQLite databases, JSON state, session files, media.
- Scheduled jobs — platform cron features or scheduler add-ons.
Step 2: Check how sessions are stored
For Telethon and Pyrogram clients, this is the step that matters most.
- If you used a string session in an environment variable — common on platforms with ephemeral disks — simply copy the variable. Nothing else to do.
- If you used a session file, download it while the bot is stopped and upload it to the same relative path on the new server. Keep the same API ID and hash; a session only works with the credentials that created it.
Never generate a new session on the server interactively — there’s no one to type the login code. Telethon and Pyrogram session files covers the details.
Step 3: Export the data
For managed 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
For MySQL, mysqldump --single-transaction and mysql do the same job. Kerit Cloud’s Telegram plans include MySQL (Free and Starter) or MySQL plus PostgreSQL (Pro and Ultra), and support can migrate a database for you if you open a ticket. Migrating a database with mysqldump and pg_dump covers the options.
Redis data is usually cache or FSM state. For conversation state, either migrate it with a dump or accept that in-progress conversations will reset.
Step 4: Prepare the new server
- Create a server on Kerit Cloud with the same runtime version.
- Upload your code, or link your repository for git deploys on paid plans.
- Recreate every environment variable in the panel. Update database URLs to point at the new database.
- Upload any SQLite databases and session files to the same relative paths.
- Set the start command.
Don’t start the bot yet.
Step 5: Handle the update mode
If the bot polls
Nothing to change in Telegram — polling works from anywhere. The only rule: the old copy must stop before the new one starts, or both poll the same token and Telegram returns 409 Conflict: terminated by other getUpdates request.
If the bot uses a webhook
Telegram delivers updates to exactly one URL. You have two choices:
- Keep webhooks — register the new server’s HTTPS endpoint with
setWebhookat cutover. Every Kerit Cloud Telegram server includes one. - Switch to polling — call
deleteWebhookand let the bot poll. This is often simpler once you’re on a host where processes don’t sleep. See long polling vs webhooks.
Either way, don’t pass drop_pending_updates during migration if you want to process messages that arrive during the switch. Telegram keeps undelivered updates for up to 24 hours, so nothing sent during a short cutover is lost.
Step 6: Cut over
- Stop the bot on the old platform (scale the worker to zero, or suspend the service).
- Take the final data export and import it, so no writes are lost.
- Point updates at the new server —
setWebhookto the new URL, ordeleteWebhookif switching to polling. - Start the bot on Kerit Cloud and watch the console.
- Test —
/start, a command that reads from the database, and any buttons.
Queued updates from the gap arrive within seconds of the new bot starting.
Step 7: Move scheduled jobs
Platform schedulers don’t come with you. Move schedules into the bot itself with a persistent job store, so restarts don’t skip or duplicate runs — see scheduling messages and background jobs.
Step 8: Clean up
After a day or two of stable running:
- Delete the old deployment so it can never start by accident and cause 409 conflicts.
- Remove secrets from the old platform, and rotate any you’ll no longer control — including the bot token via BotFather’s
/revokeif the old account is shared or being closed. - Remove keep-alive code and cancel external pingers used only to prevent sleeping.
Troubleshooting
409 Conflict — the old copy is still polling, or a webhook is still registered. Stop the old service; check getWebhookInfo.
Userbot asks for a phone number — the session didn’t come across, the path differs, or the API ID and hash don’t match the ones that created it.
Updates go to the old server — the webhook still points at the old URL. Call setWebhook with the new one.
Data looks stale — the final export happened before the old bot stopped. Re-export after stopping it.
Summary
Migrating a Telegram bot comes down to an inventory, careful handling of sessions and update mode, and a strict order at cutover: stop the old bot, export the final data, re-point or delete the webhook, then start the new one. Telegram queues updates for up to 24 hours, so a well-run migration loses nothing — and on a host with persistent processes and disks, the workarounds can finally go.