TelegramМиграцияДеплой

Как перенести Telegram-бота на другой хостинг без простоя

5 мин чтения

Бот работает на старом хостинге, и его нужно перевезти на новый — не уронив надолго и не потеряв сообщения и состояние. У Telegram-ботов переезд устроен иначе, чем у обычного веб-приложения: обновления бота получает ровно один потребитель, поэтому «поднять параллельно и переключить DNS» здесь не сработает. Разберём, как перенести бота и переключиться чисто.

Почему бота переносят не как веб-приложение

Веб-приложение при переезде можно держать в двух экземплярах одновременно и переключать трафик постепенно через DNS. С ботом так нельзя: апдейты из Telegram забирает только один консьюмер. Если запустить вторую копию с тем же токеном, при long-polling оба процесса начнут звать getUpdates и поймают 409 Conflict, а при неаккуратном webhook возможны дубли ответов.

Поэтому перенос бота — это передача одного «эстафетного жезла»: старый экземпляр перестаёт получать обновления ровно в тот момент, когда их начинает получать новый. Хорошая новость в том, что простой здесь измеряется секундами, а пропущенные сообщения Telegram какое-то время хранит сам.

Что переносим

  • код — репозиторий бота;
  • токен — в переменной окружения, не в коде;
  • состояние — FSM, сессии, данные пользователей;
  • webhook-URL — если бот работает на webhook.

Перенос состояния

Если состояние бота хранится в памяти процесса, при переезде оно потеряется — это ещё одна причина держать его во внешней базе. Если состояние в Postgres или Redis, базу переносят отдельно; как это сделать с коротким простоем, разобрано в статье про перенос PostgreSQL.

Общие шаги подготовки бота к новому хостингу — те же, что при первом размещении: зависимости, токен в окружении, база. Они описаны в статьях про размещение бота на Python и Node.js.

Переключение для long-polling

Здесь важен порядок, чтобы в каждый момент бота получал только один процесс:

  1. Развернуть бота на новом хостинге, но не запускать опрос — код готов, процесс не стартует polling.
  2. Остановить бота на старом хостинге.
  3. Запустить бота на новом.

Окно, когда бот не отвечает, — это секунды между шагами 2 и 3. Сообщения, присланные в это время, не теряются: Telegram хранит непрочитанные обновления и отдаст их новому процессу при первом getUpdates (накопленные обновления хранятся примерно сутки).

Переключение для webhook

С webhook переключение ещё чище. Адрес, на который Telegram шлёт обновления, меняется одним вызовом setWebhook — он атомарно переводит доставку на новый URL:

curl "https://api.telegram.org/bot<BOT_TOKEN>/setWebhook?url=https://new-host.example.com/webhook"

После этого Telegram перестаёт обращаться к старому адресу, и старый экземпляр можно гасить. Простоя практически нет: до вызова обновления идут на старый сервер, после — на новый.

Проверка после переключения

  • getMe — токен виден новому процессу, ответ содержит данные бота, а не 401.
  • Для webhook — getWebhookInfo: показывает текущий URL и pending_update_count (сколько обновлений ждёт доставки). URL должен быть новым, очередь — разбираться.
  • Отправить боту /start и убедиться, что отвечает именно новый экземпляр (по логам нового хостинга).
curl "https://api.telegram.org/bot<BOT_TOKEN>/getWebhookInfo"

Частые грабли

  • Два экземпляра параллельно. Старый бот не остановлен, новый запущен — 409 Conflict при long-polling или дубли ответов. Консьюмер должен быть один.
  • Состояние осталось в памяти старого процесса. После переезда бот «всё забыл», потому что данные не были в базе.
  • Webhook не переключили. Новый экземпляр запущен, но setWebhook не вызван — Telegram продолжает слать на старый адрес, и бот молчит.
  • Старый webhook не снят при переходе на long-polling. Если бот переезжает с webhook на polling, старый webhook нужно удалить (deleteWebhook), иначе getUpdates не будет получать обновления.

Чеклист

  • Состояние бота — во внешней базе, база перенесена и сверена.
  • Токен задан в окружении на новом хостинге.
  • Для long-polling: новый экземпляр поднят, но не опрашивает, пока не остановлен старый.
  • Для webhook: setWebhook переключён на новый URL, старый адрес погашен.
  • getMe и getWebhookInfo подтверждают, что обновления идут новому экземпляру.
  • Старый хостинг выключен только после проверки, что отвечает новый.

Перенос проходит спокойнее, когда новый хостинг не требует ручной настройки процесса, базы и SSL. На Hostim бот разворачивается по git push и работает 24/7 без serverless-засыпания, managed Postgres под состояние идёт с ежедневными бэкапами, а для webhook домен и SSL поднимаются автоматически — остаётся только переключить доставку обновлений.

Читать дальше