Telegraft

Справочник по Bot API

Потолок в 30 сообщений в секунду

Telegram-бот отправляет примерно 30 сообщений в секунду суммарно по всем чатам. Лимит применяет сервер — ответом 429 со значением retry_after, — он не опубликован как жёсткое число и считается на бота целиком, а не на каждого получателя отдельно.

Лимит скорости рассылки: точные цифры

Устойчивая скорость отправки
~30 сообщений в секунду, на бота целиком, суммарно по всем чатам
Устойчивая скорость
~30 сообщений в секунду, на бота целиком
Область действия
На токен бота, не на чат и не на процесс
Ответ сервера
HTTP 429 со значением retry_after в секундах
40 000 подписчиков
~22 минуты на потолке, без учёта сбоев

As of 2025-10-01, Telegram Bot API 13.4

Что это значит на практике

Практическое следствие — арифметика, и она обычно застаёт врасплох. Сорок тысяч подписчиков при тридцати сообщениях в секунду — это двадцать две минуты непрерывной отправки, если ничего не падает и никто больше не претендует на тот же бюджет. Акцию, которая обязана дойти до всех до начала события, нельзя запускать в момент начала события.

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

Telegram намеренно не публикует это как фиксированную цифру. В документации примерно тридцать в секунду описаны как безопасная устойчивая скорость с оговоркой, что короткие всплески могут проходить, — а значит наивная реализация выглядит рабочей на малых объёмах и ломается ровно на том объёме, ради которого её писали. Считать число точным — ошибка в другую сторону: правильная позиция это держать темп ниже потолка и обрабатывать 429 как штатное событие, а не как аварию.

Работающая форма — очередь с token bucket перед ней, сохранённая в хранилище, а не в памяти процесса. Каждая отправка забирает токен; корзина пополняется чуть медленнее потолка; ответ 429 останавливает корзину ровно на тот retry_after, который назвал сервер, а не на угаданный интервал. Очередь сохранена — значит перезапуск воркера посреди рассылки продолжает её, а не начинает заново, и это важнее, чем звучит: перезапуск незавершённой рассылки означает второе сообщение первым нескольким тысячам человек.

Планирование заслуживает отдельного внимания. Отправка занимает реальное время, поэтому напоминание, которое обязано прийти в конкретную минуту, нельзя отправлять в эту минуту. Очередь наполняют заранее и задают темп так, чтобы последнее сообщение легло вовремя, — то есть проектный вопрос звучит как «какое окно допустимо», а не «в какой момент целимся». Для напоминаний о записи окно нормально, для оповещения об открытии рынка обычно нет, и это ограничение обсуждают при согласовании объёма работ, а не в разборе после запуска.

Как это обрабатывать в коде

// Paced send with a token bucket and honest 429 handling.
const RATE_PER_SECOND = 25 // deliberately under the ~30 ceiling
let tokens = RATE_PER_SECOND
setInterval(() => { tokens = RATE_PER_SECOND }, 1000)

async function sendPaced(chatId: number, text: string): Promise<void> {
  while (tokens <= 0) await new Promise((r) => setTimeout(r, 50))
  tokens -= 1

  try {
    await bot.api.sendMessage(chatId, text)
  } catch (error) {
    // 429 is a normal event on a broadcast, not an exception. Honour the server's
    // retry_after rather than a guessed backoff, then requeue this recipient.
    const retryAfter = (error as { parameters?: { retry_after?: number } })
      .parameters?.retry_after
    if (retryAfter !== undefined) {
      tokens = 0
      await new Promise((r) => setTimeout(r, retryAfter * 1000))
      return sendPaced(chatId, text)
    }
    throw error
  }
}
Темп держится ниже потолка, а 429 считается ожидаемым событием. Рекурсивный повтор безопасен здесь только потому, что корзина сначала обнуляется: мгновенный повтор после 429 — это ровно тот способ, которым бот зарабатывает себе паузу подлиннее.

Какие вопросы это порождает

Поднимут ли лимит дополнительные экземпляры бота?

Нет. Бюджет принадлежит токену бота, поэтому десять воркеров делят одни и те же тридцать сообщений в секунду и по умолчанию согласуются между собой плохо: каждый считает, что вся квота его, и рассылка ловит 429 сразу. Если воркеров несколько, token bucket обязан быть общим состоянием, а не переменной внутри каждого процесса.

Тридцать сообщений в секунду — это задокументированный жёсткий лимит?

Это рекомендация, а не контракт. Telegram описывает примерно тридцать в секунду как безопасную скорость для длительной отправки и отмечает, что короткие всплески могут проходить. Строить расчёт на точном числе неразумно в обе стороны: держите темп ниже него и обрабатывайте 429 как нормальную часть потока.

Что будет, если игнорировать 429 и продолжать отправку?

Значения retry_after начинают расти, и отправка сквозь них — это ровно то, что превращает временное притормаживание в длительное ограничение. Сервер прямо называет, сколько ждать; угадать интервал покороче — самый частый способ для рассылки ухудшить собственное положение.

Можно ли попросить поднять лимит?

Для действительно крупных сценариев рассылки Telegram исторически был готов обсуждать с владельцами ботов повышенные лимиты, но это не настройка в кабинете, и закладываться на неё при согласовании объёма нельзя. Проектируйте под стандартный потолок, а любое повышение считайте бонусом, а не зависимостью.

Смежные ограничения