EvolCode
треки/Телеграм-боты·01 / 06
13 мин чтения

Деплой бота — webhook vs polling и где хостить

Локально бот работает на длинном polling — раз в секунду спрашивает у Telegram «что нового?». На проде это работает, но плохо: лишний траффик, медленная реакция на сообщения, и ты обязан держать процесс живым 24/7. Webhook переворачивает схему: Telegram сам стучится к твоему серверу когда приходит сообщение. Это быстрее, дешевле, но требует HTTPS-эндпоинта. Разберёмся когда что использовать и как задеплоить.

Polling — простой, но не для прода

Long polling работает так: твой клиент делает запрос к Telegram getUpdates с большим timeout (~50 секунд). Telegram держит соединение открытым и отвечает как только появятся сообщения, или через 50 секунд если ничего не было. Плюсы: ничего не настраивать, работает за NAT, легко отлаживать локально. Минусы: один процесс должен быть живой ВСЕГДА, при перезапуске лагает 50 секунд, на пиковой нагрузке упирается в одно соединение. Подходит для прототипов и личных ботов.

Webhook — правильный путь для прода

Ты регистрируешь у Telegram URL вида

$ https://yourdomain.com/bot/webhook

Когда приходит сообщение, Telegram сам делает POST на этот URL с update в теле. Плюсы: реакция мгновенная, бот может быть serverless (запускаться по запросу), масштабируется горизонтально. Требования: HTTPS обязательно, валидный сертификат (Let's Encrypt бесплатный), порт 80/443/88/8443. Регистрация через bot.api.setWebhook(url) один раз. После этого polling больше не работает (либо одно либо другое).

Где хостить — 4 варианта

(1) Свой VPS (DigitalOcean, Hetzner, Timeweb) — $4-6/мес, полный контроль, нужно настраивать nginx + systemd + Let's Encrypt. Хорошо для polling и для webhook. (2) Vercel — для serverless webhook на Next.js, бесплатно для небольшой нагрузки. POST на /api/webhook/route.ts обрабатывает каждое сообщение в отдельной функции. (3) Cloudflare Workers — глобальный edge, дёшево, низкая задержка. Идеально для webhook. (4) Railway/Render — managed VPS, чуть дороже DO но проще настроить (push в git → задеплоилось). Для большинства case-ов выбирай Cloudflare Workers (если знаком) или Railway (если хочешь чтоб just works).

Безопасность вебхука — секрет токен

Telegram даёт всему интернету твой webhook URL. Кто угодно может слать туда фейковые update и притворяться Telegram-ом. Защита: при setWebhook передаёшь secret_token. Telegram включает его в заголовок X-Telegram-Bot-Api-Secret-Token каждого запроса. Твой обработчик первым делом проверяет этот заголовок — если не совпадает, отвечает 401. Без этого любой может отправить тебе фейковый update и заставить бота сделать что-то от имени админа.

Anti-flood и масштаб

Telegram ограничения: 30 сообщений/сек на разных юзеров, 1 сообщ/сек на одного юзера, 20 сообщ/мин в один групповой чат. Если бьёшь лимит — получаешь 429 с retry_after. У grammY есть встроенный rate limiter, для самописа — exponential backoff. Под нагрузкой webhook + serverless = масштаб бесплатно. Polling = упрёшься в один процесс. Если бот популярный (100+ сообщ/сек) — обязательно webhook + очередь: webhook просто кладёт update в Redis/SQS, воркеры разбирают. Иначе на пике сервер ляжет.

примерtypescript
// app/api/webhook/route.ts
import { NextResponse } from 'next/server';
import { Bot, webhookCallback } from 'grammy';

const bot = new Bot(process.env.BOT_TOKEN!);

bot.command('start', (ctx) => ctx.reply('Привет с serverless!'));
bot.on('message:text', (ctx) => ctx.reply(`Эхо: ${ctx.message.text}`));

const handler = webhookCallback(bot, 'std/http');

export async function POST(req: Request) {
  // 1. Проверка secret token
  const secret = req.headers.get('x-telegram-bot-api-secret-token');
  if (secret !== process.env.WEBHOOK_SECRET) {
    return NextResponse.json({ ok: false }, { status: 401 });
  }
  // 2. Передаём в grammY
  return handler(req);
}

// Один раз — регистрация webhook (запустить в скрипте при первом деплое):
// import { Bot } from 'grammy';
// const bot = new Bot(process.env.BOT_TOKEN!);
// await bot.api.setWebhook('https://yourdomain.vercel.app/api/webhook', {
//   secret_token: process.env.WEBHOOK_SECRET,
//   drop_pending_updates: true,
// });
// console.log('Webhook set');

// .env:
// BOT_TOKEN=12345:abc...
// WEBHOOK_SECRET=любая_длинная_случайная_строка_32_символа

// Деплой:
// 1. git push в Vercel
// 2. В дашборде Vercel добавить env-переменные
// 3. Запустить скрипт setWebhook один раз
// 4. Бот живёт без сервера 24/7, ты не платишь пока никто не пишет

Webhook на Next.js — деплой на Vercel за 5 минут

главное
  • 01Polling — для разработки и прототипов. Webhook — для прода. Они взаимоисключающие.
  • 02Webhook требует HTTPS-эндпоинт и secret_token для защиты от фейковых запросов.
  • 03Самый простой деплой — Cloudflare Workers или Vercel + Next.js. Без сервера, бесплатно для небольшой нагрузки.
  • 04Telegram-лимиты: 30/сек глобально, 1/сек на юзера, 20/мин в группу. Под пиком — webhook + очередь.
  • 05setWebhook делается ОДИН раз. После этого polling не работает — видеть updates можно только через webhook.
проверь себя
01Чем webhook принципиально отличается от polling?
02Зачем при setWebhook передавать secret_token?
03Что произойдёт если у тебя зарегистрирован webhook, и ты запустишь bot.start() (polling)?
← к треку