Telegram
9 мин·

Telegram webhook vs polling: что выбрать для уведомлений

Подробное сравнение webhook и long polling в Telegram Bot API: производительность, надёжность и сценарии использования.

Два способа получения обновлений

Telegram Bot API предоставляет два способа получения входящих сообщений и событий: long polling (метод getUpdates) и webhook (метод setWebhook). Выбор между ними влияет на архитектуру, производительность и надёжность вашего приложения.

В этой статье мы подробно разберём оба подхода, сравним их показатели и дадим конкретные рекомендации. Если вы строите систему доставки, посмотрите также статью об отказоустойчивой архитектуре.

ХарактеристикаPolling (getUpdates)Webhook
ИнициаторВаш серверTelegram
ПротоколHTTP-запросы к APIHTTPS 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
Прототип / MVPPolling — быстро и просто
Бот до 100 пользователейPolling — достаточно для малого трафика
Production-бот (1 000+ пользователей)Webhook — низкая задержка, масштабируемость
Бизнес-уведомленияWebhook — мгновенная реакция критична
Серверless (AWS Lambda, CF Workers)Webhook — нет постоянного процесса
Мультиканальная системаРелая — обрабатывает всё автоматически

Настройка вебхуков: безопасность

При использовании webhook критически важно обеспечить безопасность:

  1. Используйте secret_token: передайте секретный токен при регистрации webhook. Telegram будет отправлять его в заголовкеX-Telegram-Bot-Api-Secret-Token.
  2. Проверяйте IP-адреса Telegram: обновления приходят с IP 149.154.160.0/20 и 91.108.4.0/22. Фильтруйте остальные на уровне файрвола.
  3. Используйте уникальный URL: не ставьте webhook на очевидный путь вроде /webhook. Используйте URL с токеном: /webhook/abc123secret.
  4. HTTPS обязателен: Telegram не будет слать обновления по HTTP. Используйте Let's Encrypt или Cloudflare для бесплатного SSL.
  5. Ограничьте 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, отправьте себе тестовое сообщение и уже потом решайте, нужны ли другие каналы.