Telegram Bots

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
  1. Why Telegram bots outgrow these platforms
  2. Step 1: Inventory your bot
  3. Step 2: Check how sessions are stored
  4. Step 3: Export the data
  5. Step 4: Prepare the new server
  6. Step 5: Handle the update mode
  7. Step 6: Cut over
  8. Step 7: Move scheduled jobs
  9. Step 8: Clean up
  10. Troubleshooting
  11. Summary

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.yaml or dashboard settings.
  • Environment variables — every name and value, including BOT_TOKEN, database URLs, API keys, and TG_API_ID/TG_API_HASH/session strings for MTProto clients.
  • Update mode — polling or webhook. If webhook, note the current URL (getWebhookInfo shows 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

  1. Create a server on Kerit Cloud with the same runtime version.
  2. Upload your code, or link your repository for git deploys on paid plans.
  3. Recreate every environment variable in the panel. Update database URLs to point at the new database.
  4. Upload any SQLite databases and session files to the same relative paths.
  5. 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 setWebhook at cutover. Every Kerit Cloud Telegram server includes one.
  • Switch to polling — call deleteWebhook and 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

  1. Stop the bot on the old platform (scale the worker to zero, or suspend the service).
  2. Take the final data export and import it, so no writes are lost.
  3. Point updates at the new server — setWebhook to the new URL, or deleteWebhook if switching to polling.
  4. Start the bot on Kerit Cloud and watch the console.
  5. 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 /revoke if 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.