Telegram webhook vs polling: что выбрать для уведомлений
Подробное сравнение webhook и long polling в Telegram Bot API: производительность, надёжность и сценарии использования.
Два способа получения обновлений
Telegram Bot API предоставляет два способа получения входящих сообщений и событий: long polling (метод getUpdates) и webhook (метод setWebhook). Выбор между ними влияет на архитектуру, производительность и надёжность вашего приложения.
В этой статье мы подробно разберём оба подхода, сравним их показатели и дадим конкретные рекомендации. Если вы строите систему доставки, посмотрите также статью об отказоустойчивой архитектуре.
| Характеристика | Polling (getUpdates) | Webhook |
|---|---|---|
| Инициатор | Ваш сервер | Telegram |
| Протокол | HTTP-запросы к API | HTTPS POST на ваш URL |
| Задержка | 0–50 секунд (зависит от timeout) | Миллисекунды |
| Требования к серверу | Любой (даже без публичного IP) | Публичный HTTPS-адрес |
| Масштабирование | Один процесс | Горизонтальное (балансировщик) |
| Сложность реализации | Простая | Средняя |
| Подходит для | Разработка, малые боты | Production, высокая нагрузка |
Как работает polling (getUpdates)
При polling ваш сервер периодически вызывает метод getUpdates, запрашивая новые события. Telegram возвращает массив обновлений (до 100 за запрос). Long polling добавляет параметр timeout — сервер Telegram будет удерживать соединение до появления нового события.
// Polling-цикл для Telegram Bot API
async function startPolling(token) {
let offset = 0;
const TIMEOUT = 30; // секунды long polling
console.log("Polling started...");
while (true) {
try {
const res = await fetch(
`https://api.telegram.org/bot${token}/getUpdates?` +
`offset=${offset}&timeout=${TIMEOUT}&allowed_updates=["message","callback_query"]`
);
const data = await res.json();
if (!data.ok) {
console.error("getUpdates error:", data.description);
await sleep(5000);
continue;
}
for (const update of data.result) {
// Обрабатываем каждое обновление
await handleUpdate(update);
// Сдвигаем offset, чтобы не получить повторно
offset = update.update_id + 1;
}
} catch (err) {
console.error("Polling error:", err.message);
await sleep(5000); // Пауза при ошибке сети
}
}
}
async function handleUpdate(update) {
if (update.message) {
console.log(`Сообщение от ${update.message.from.first_name}: ${update.message.text}`);
// Обработка команд, текста и т.д.
}
if (update.callback_query) {
console.log(`Callback: ${update.callback_query.data}`);
// Обработка нажатия кнопки
}
}
function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}
startPolling("YOUR_BOT_TOKEN");Плюсы и минусы polling
- ✅ Не требует публичного IP и SSL-сертификата
- ✅ Прост в реализации и отладке
- ✅ Работает за NAT и файрволом
- ✅ Вы контролируете частоту запросов
- ❌ Задержка доставки 0–30 секунд
- ❌ Нагрузка на сервер Telegram (постоянные запросы)
- ❌ Не масштабируется горизонтально (один consumer)
- ❌ При падении процесса — потеря обновлений (если offset не сохранён)
Как работают вебхуки
При использовании webhook Telegram сам отправляет HTTP POST-запрос на указанный вами URL при каждом новом событии. Это push-модель — ваш сервер пассивно ждёт входящие запросы.
// Webhook-сервер на Express.js
import express from "express";
import crypto from "crypto";
const app = express();
app.use(express.json());
const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN;
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
// Верификация запроса от Telegram
function verifyTelegramRequest(req) {
const secret = req.headers["x-telegram-bot-api-secret-token"];
return secret === WEBHOOK_SECRET;
}
// Обработчик webhook
app.post("/webhook/telegram", (req, res) => {
// Проверяем, что запрос действительно от Telegram
if (!verifyTelegramRequest(req)) {
console.warn("Unauthorized webhook request");
return res.sendStatus(401);
}
const update = req.body;
// Обрабатываем обновление асинхронно
processUpdate(update).catch((err) =>
console.error("Error processing update:", err)
);
// ВАЖНО: ответить быстро (< 60 сек), иначе Telegram перестанет слать
res.sendStatus(200);
});
async function processUpdate(update) {
if (update.message) {
const { chat, text, from } = update.message;
console.log(`[${chat.id}] ${from.first_name}: ${text}`);
// Пример ответа
if (text === "/start") {
await sendMessage(chat.id, "Добро пожаловать! 👋");
}
}
if (update.callback_query) {
const { data, from } = update.callback_query;
console.log(`Callback от ${from.first_name}: ${data}`);
}
}
async function sendMessage(chatId, text) {
await fetch(
`https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ chat_id: chatId, text }),
}
);
}
// Регистрация webhook
async function setWebhook() {
const DOMAIN = process.env.DOMAIN; // например: https://api.example.com
const res = await fetch(
`https://api.telegram.org/bot${BOT_TOKEN}/setWebhook`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: `${DOMAIN}/webhook/telegram`,
secret_token: WEBHOOK_SECRET,
allowed_updates: ["message", "callback_query"],
max_connections: 40,
}),
}
);
const data = await res.json();
console.log("Webhook set:", data);
}
app.listen(3000, async () => {
console.log("Server running on :3000");
await setWebhook();
});Плюсы и минусы webhook
- ✅ Мгновенная доставка обновлений (миллисекунды)
- ✅ Нет лишних запросов к Telegram
- ✅ Масштабируется горизонтально за балансировщиком
- ✅ Автоматическая повторная доставка при ошибке
- ❌ Требуется публичный HTTPS-адрес
- ❌ Нужен SSL-сертификат (self-signed или Let's Encrypt)
- ❌ Сложнее отлаживать локально (нужен ngrok или подобное)
- ❌ Необходимо быстро отвечать 200 OK (до 60 секунд)
Сравнение производительности
По внутренним тестам в Релая на типичной нагрузке, показатели выглядят примерно так (ориентиры, зависят от инфраструктуры и трафика):
| Показатель | Polling (timeout=30) | Webhook |
|---|---|---|
| Средняя задержка | ~15 секунд | ~200 мс |
| P99 задержка | ~30 секунд | ~800 мс |
| CPU нагрузка (idle) | Минимальная | Близка к нулю |
| Сетевой трафик (idle) | ~1 запрос/30 сек | Почти 0 |
| Потеря обновлений при рестарте | Возможна (без offset) | Telegram перешлёт |
| Макс. throughput | ~100+ updates/sec | сотни–тысячи updates/sec |
Вывод из тестов: для production-нагрузок webhook обычно выигрывает по задержке и throughput. Polling оправдан для разработки и маленьких ботов (до 100 пользователей).
Надёжность и отказоустойчивость
Надёжность — ключевой фактор для бизнес-критичных ботов. Сравним оба подхода:
Polling: сценарии отказа
- Падение процесса: если offset не сохранён — потеря обновлений. Если сохранён — повторная обработка последних событий.
- Сетевой сбой: polling автоматически восстановится при следующей попытке. Обновления хранятся на серверах Telegram до 24 часов.
- Медленная обработка: блокирует получение новых обновлений (однопоточная модель по умолчанию).
Webhook: сценарии отказа
- Сервер недоступен: Telegram повторит доставку несколько раз с экспоненциальным backoff. Максимальное время хранения — до нескольких часов.
- Медленный ответ (>60 сек): Telegram закроет соединение и пометит webhook как нестабильный. Частые таймауты приведут к деактивации.
- Невалидный SSL: webhook будет отключён, пока сертификат не станет валидным.
Рекомендация: при использовании webhook всегда отвечайте 200 OK мгновенно, а обработку выполняйте асинхронно (через очередь). Это снижает риск отключения webhook со стороны Telegram. Подробнее об отказоустойчивости — в статье отказоустойчивая система доставки.
Когда что использовать
Выбор зависит от ваших требований и инфраструктуры:
| Сценарий | Рекомендация |
|---|---|
| Локальная разработка | Polling — не нужен публичный IP |
| Прототип / MVP | Polling — быстро и просто |
| Бот до 100 пользователей | Polling — достаточно для малого трафика |
| Production-бот (1 000+ пользователей) | Webhook — низкая задержка, масштабируемость |
| Бизнес-уведомления | Webhook — мгновенная реакция критична |
| Серверless (AWS Lambda, CF Workers) | Webhook — нет постоянного процесса |
| Мультиканальная система | Релая — обрабатывает всё автоматически |
Настройка вебхуков: безопасность
При использовании webhook критически важно обеспечить безопасность:
- Используйте secret_token: передайте секретный токен при регистрации webhook. Telegram будет отправлять его в заголовке
X-Telegram-Bot-Api-Secret-Token. - Проверяйте IP-адреса Telegram: обновления приходят с IP 149.154.160.0/20 и 91.108.4.0/22. Фильтруйте остальные на уровне файрвола.
- Используйте уникальный URL: не ставьте webhook на очевидный путь вроде
/webhook. Используйте URL с токеном:/webhook/abc123secret. - HTTPS обязателен: Telegram не будет слать обновления по HTTP. Используйте Let's Encrypt или Cloudflare для бесплатного SSL.
- Ограничьте allowed_updates: получайте только нужные типы обновлений — это снижает трафик и уменьшает поверхность атаки.
// Безопасная регистрация webhook
async function setupSecureWebhook(token, domain) {
const secretToken = crypto.randomBytes(32).toString("hex");
const res = await fetch(
`https://api.telegram.org/bot${token}/setWebhook`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: `${domain}/webhook/tg-${token.split(":")[0]}`,
secret_token: secretToken,
allowed_updates: ["message", "callback_query", "my_chat_member"],
max_connections: 40,
drop_pending_updates: false,
}),
}
);
const data = await res.json();
if (data.ok) {
console.log("Webhook установлен. Secret:", secretToken);
// Сохраните secretToken для верификации входящих запросов
}
return { secretToken, result: data };
}Как Релая обрабатывает входящие
При использовании Релая вам не нужно выбирать между polling и webhook, настраивать SSL или думать о безопасности. Платформа:
- Автоматически использует webhook для Telegram, MAX и VK — обеспечивая минимальную задержку
- Обрабатывает retry и failover: если webhook временно недоступен, Релая автоматически переключается на polling и обратно
- Единый формат обновлений: не важно, из какого мессенджера пришло сообщение — вы получаете его в едином формате через API или webhook
- Безопасность из коробки: проверка подписи, фильтрация IP, rate limiting входящих — всё настроено
- Горизонтальное масштабирование: Релая обрабатывает миллионы входящих обновлений в день
Итог: для production-систем webhook обычно является предпочтительным выбором. Для максимальной надёжности используйте Релая, которая не только обрабатывает входящие от Telegram, но и объединяет MAX и другие каналы в единую систему. Это даёт вам отказоустойчивость и скорость без инфраструктурных затрат.
Создайте бесплатный MAX-профиль
Если хочется не просто читать, а сразу проверить сценарий руками: подключите MAX, отправьте себе тестовое сообщение и уже потом решайте, нужны ли другие каналы.