Бот перестал работать в телеграм? Я покажу, что критично проверить сразу (токен, вебхук, TLS) и что важно. Когда токен, вебхук и TLS уже исправны, проверьте воронку на реальных пользователях малыми волнами трафика: Накрутка подписчиков телеграм даст быстрый контрольный приток для замера welcome-сообщений, отклика бота и удержания. Фиксируйте p95 ответа, error rate и конверсию в целевое действие до и после запуска.
Нужны первоисточники, чтобы доверять каждому шагу? Сверяйтесь с документацией Telegram Bot API: setWebhook/getUpdates/лимиты – https://core.telegram.org/bots/api. Требования к HTTPS и сертификатам (публичный CA, полный chain, SNI/CN) – https://core.telegram.org/bots/webhooks#https-certificate. Про Privacy Mode у BotFather – https://core.telegram.org/bots/features#privacy-mode.
Сначала закрываем Критично: токен/дубликаты, 409 (двойной канал апдейтов), TLS chain/CN/SNI, быстрый 200 OK. Затем Важно: IPv6/AAAA и DNS, лимиты 429 (частые запросы), права/Privacy Mode. Опционально: окна тишины в cron, circuit breaker (автовыключатель запросов) и тонкие настройки очередей. Такая маркировка экономит время и снижает MTTR.
Токен не меняли вчера и он не отозван (/revoke у BotFather)? Бот добавлен админом там, где должен писать (группа/канал) и ему выданы нужные права? Включён ли Privacy Mode и не мешает ли он чтению обычных сообщений в группах (при включении бот видит только команды)? В моей практике 3 из 10 инцидентов закрываются уже на этом шаге.
Как бот получает события сейчас – webhook или long polling (опрос)? Если webhook, вызовите getWebhookInfo и убедитесь, что ваш URL стабильно возвращает 200 OK за 1–2 секунды. Для отладки временно снимите webhook и включите polling (не одновременно, иначе будет 409 Conflict). Такой переключатель сразу показывает: у нас сеть/сертификат или логика кода.
Открывается ли ваш домен по HTTPS без предупреждений? Проверьте цепочку сертификата и SNI (имя сервера в TLS), а также CN (имя домена в сертификате) – ошибки тут «глушат» вебхук. Посмотрите DNS и маршруты: нет ли рассинхрона IPv4/IPv6 и не режет ли фаервол исходящие/входящие. Часто это самый быстрый фикс без правок кода.
Сравните токен в переменных окружения с токеном у BotFather – не разъехались ли dev/stage/prod. Если делали /revoke или получили новый /token, старый ключ сразу мёртв – обновите секреты в CI/CD и перезапустите воркеры. Проверьте дубликаты окружений, где мог остаться старый ключ. В моей практике именно рассинхрон токенов валил бота на часы.
Активен ли только один канал доставки событий? 409 Conflict в API почти всегда значит, что запущены оба. Для локальной проверки снимите webhook (deleteWebhook с drop_pending_updates) и включите getUpdates. Так вы исключите сеть и посмотрите на обработчик апдейтов в лоб.
Вызовите getWebhookInfo и прочтите last_error_message: timeout, TLS error, wrong response? Timeout – обработчик отвечает слишком долго; TLS error – проблема с сертификатом/цепочкой; wrong response – не 200 OK или не тот формат ответа. Логируйте входящий payload (тело запроса) и время ответа – это экономит часы.
Используйте публичный CA и отдавайте полный chain (intermediate сертификаты). Убедитесь, что SNI (имя сервера) и CN (домен в сертификате) совпадают с URL вебхука. Возвращайте 200 OK быстро: лучше до 2 секунд, максимум до 10 секунд. В реальных инцидентах неполная цепочка была самой частой причиной «тишины».
Проверьте логи на 429 Too Many Requests и включите бэкофф (повторные попытки по экспоненте). Сверьте размеры файлов и длины полей (особенно callback_data) с лимитами Bot API. Валидируйте JSON и типы апдейтов, чтобы неожиданные события не «роняли» обработчик. Идемпотентность (без повторной обработки) спасает от дублей при ретраях.
Боту хватает прав на отправку сообщений, ссылок и медиа там, где он «молчит»? В группах с включённым Privacy Mode бот видит только команды и инлайн – это не баг. В каналах писать получится только с правами администратора. Мы заранее перечисляем требования к правам, чтобы их не потеряли при миграции.
Включите подробный лог: входящий апдейт, ID чата, время обработки, статус ответа. Поймайте непойманные исключения и проверьте очереди сообщений – нет ли «залипаний». Вынесите внешние вызовы в фон, поставьте таймауты (время ожидания ответа) и circuit breaker (автовыключатель запросов). Это стабилизирует 200 OK и уменьшит подвисания.
Проверьте, не режет ли прокси/фаервол входящие и исходящие запросы. Убедитесь, что health‑checks (URL проверки здоровья сервиса) не убивают воркер под нагрузкой. Нет ли проблем с DNS/TTL при переезде домена и не мешает ли AAAA‑запись для IPv6. Мониторинг задержек и аптайма даст ранний сигнал деградации.
Храните токен в секрет‑менеджере и распространяйте через один источник правды. После /revoke обновляйте все среды, иначе часть воркеров останется с «мертвым» ключом. Проверьте, не запущены ли старые контейнеры с прежними переменными окружения. Это классика, которая ломает прод на ровном месте.
Проверьте /setcommands и локализованные описания – первая строка видна сразу в клиенте. Соблюдайте формат: слэш, команда, короткое описание без «воды» и лишних символов. Для нескольких языков держите отдельные наборы, чтобы клиент подхватывал локаль пользователя. Мы заливаем команды из JSON на релизе, чтобы не править руками.
Решите заранее: бот читает всё или только команды? Если нужно читать обычные сообщения, выключите Privacy Mode (и добавьте фильтры по чатам). Для публикации в канале дайте права администратора и отметьте нужные галочки. Так не придётся «ждать чуда» от приватного бота.
Регистрируйте вебхук на доступном извне HTTPS‑домене. Придерживайтесь правила «один бот – один вебхук», без дублей и старых хвостов. Перед переключением делайте drop_pending_updates, чтобы не тянуть старые апдейты. Мы всегда проверяем health‑endpoint до включения реального трафика.
Следите за сроком действия и целостностью цепочки, совпадением CN/домена и корректным SNI. На мультисайтовых серверах проверьте виртуальные хосты и роутинг. Неправильный SNI/CN выглядит как «молчание» без явной ошибки в логах. Это чинится за минуты, если знать куда смотреть.
Возвращайте 200 OK сразу, тяжёлое уносите в фоновые очереди. Ставьте ретраи (повторные попытки) и идемпотентность (без повторной обработки) на чувствительных участках. Логируйте время ответа и ID апдейта, чтобы ловить шипы. В моей практике перенос внешних вызовов в фон мгновенно снял «таймауты».
Держите timeout 25–30 секунд и сдвигайте offset, чтобы не ловить дубли. Храните last_update_id и применяйте идемпотентность (без повторной обработки). Не блокируйте получение апдейтов тяжёлыми задачами. Polling – быстрый способ изолировать проблему от сети/TLS.
Делегируйте долгие операции воркерам и очередям, а не держите их в обработчике. Контролируйте число параллельных воркеров и лимиты Bot API, чтобы не ловить 429. Добавьте метрики очередей и активных обработчиков в мониторинг. Это делает поведение бота предсказуемым под нагрузкой.
Снимайте вебхук с drop_pending_updates перед запуском polling – и наоборот. Фиксируйте шаги в журнале релиза, чтобы не получить 409 Conflict. Держите один канал апдейтов в каждый момент времени. Так вы избежите двойной доставки и странных багов.
Сверьте лимиты по размеру файлов и частоте запросов в документации Bot API. Включите бэкофф и очереди на массовых отправках, чтобы не ловить 429 Too Many Requests. Соблюдайте лимиты на чат и на бота, иначе сообщения будут «отскакивать». Мы ставим алерты на приближение к порогам, чтобы реагировать заранее.
Не кладите большие JSON в callback_data – храните состояние на сервере. Валидируйте длины полей, шифруйте или кодируйте маркеры компактно. Экранируйте пользовательский ввод, чтобы не «ломать» Markdown/HTML. Простые маркеры + серверное состояние = надёжность и скорость.
Отправляйте корректный Content‑Type и валидный JSON на входе/выходе. Учитывайте Unicode, эмодзи, RTL‑текст и длинные подписи. Автотесты на сериализацию спасают часы в проде. Мы держим заглушки на редкие события, чтобы бот не падал молча.
Проверьте галочки прав на отправку сообщений, ссылок, медиа и управление сообщениями. В канале без админки бот писать не будет – так устроено. Для закрепов и ссылок нужны отдельные разрешения – уточните это заранее. Мы всегда описываем требуемые права в README проекта.
Супергруппы включают антифлуд и slow‑mode – визуально бот «молчит». Проверьте фильтры и режим «только админы», а также Privacy Mode. Если нужен доступ к обычным сообщениям – выключайте Privacy Mode или работайте командами. Тест в песочнице экономит много нервов.
403 Forbidden в личке = пользователь заблокировал бота. Не шлите повторно и не сжигайте лимиты – уважайте выбор пользователя. Дайте инструкцию по разблокировке в FAQ и интерфейсе. Это уменьшает жалобы и повышает доверие к боту.
Откройте исходящие на api.telegram.org:443 и входящие на порт вебхука. За NAT/прокси проверьте заголовки X‑Forwarded и реальный IP клиента. При необходимости добавьте IP Telegram в белые списки хостинга. Мы регулярно делаем трассы и проверяем MTU при нестабильной сети.
Проверьте A/AAAA записи и TTL, особенно после переезда домена. Несовместимость IPv6 вызывает таймауты на части клиентов – отключите AAAA или настройте поддержку. Подождите распространения DNS перед переключением вебхука. Эти мелочи часто объясняют «мистические» отказы.
Сверьте таймауты функций и лимиты по памяти/CPU – при недогрузке всё «висит». Холодный старт ломает 200 OK – держите «тёплый» пул или пинг по расписанию. Следите за p95 задержкой и временем до ответа: это ранние индикаторы проблем. В нашем опыте это ловит деградацию раньше, чем пользователи её заметят.
Включите глобальный перехват ошибок и алерты на падения процессов. Следите за длиной очередей и признавайте сообщения (ack), чтобы не плодить дубли. Проверяйте утечки памяти, чтобы воркеры не умирали тихо. Watchdog‑перезапуск часто возвращает доступность без редеплоя.
Сверьте список типов апдейтов и добавьте заглушки на редкие события. Логируйте неожиданные payload (тело запроса), чтобы быстро видеть причину падения. Расширьте тесты: poll, shipping_query, pre_checkout_query, chat_join_request. Так вы не поймаете сюрприз в проде.
Проверьте таймзону сервера и расписание cron – не мешают ли они обработке апдейтов. Добавьте окна тишины для ночных часов, если пользователям лучше не писать. Разведите cron и воркеры по очередям, чтобы не блокировать друг друга. Это убирает «мистические» провалы вовлечения.
Держите ключи в секрет‑хранилище и проверяйте квоты заранее. Следите за SLA партнёров и готовьте «план Б» при недоступности. Храните ссылки на статус‑страницы поставщиков. Мы добавляем кеш и фолбэки, чтобы бот не зависел от чужих шипов.
Ставьте таймауты (время ожидания ответа) и ретраи (повторные попытки) на внешних вызовах. Включайте circuit breaker (автовыключатель запросов), чтобы не перегружать сервисы. Сообщайте пользователю дружелюбные тексты при деградации. Это сохраняет доверие и лимиты.
Санитизируйте Markdown/HTML и экранируйте спецсимволы. Валидируйте длины/типы, даже если «по документации всё ок». Не доверяйте внешним JSON и проверяйте поля на входе. Такой слой защиты избавляет от неожиданных падений.
| Код/статус | Ситуация | Диагноз | Действие |
|---|---|---|---|
| 400 Bad Request | Неверный JSON/параметр | Валидация упала | Исправьте поле/тип и пересоберите |
| 401 Unauthorized | Неверный токен | Токен отозван/ошибочный | Получите новый в BotFather |
| 403 Forbidden | Нет прав/заблокирован | PM запрещён/не админ | Запросите права/инвайт |
| 409 Conflict | Два канала апдейтов | Webhook+polling одновременно | Отключите одно, deleteWebhook |
| 413 Payload Too Large | Слишком большой файл | Превышены лимиты | Сжимайте/делите |
| 429 Too Many Requests | Rate limit | Частые запросы | Бэкофф, очереди |
| 502/504 Upstream | Сеть/шлюз | Временный сбой | Ретраи, мониторинг |
| webhook last_error | Не 200 OK/TLS | Сервер не отвечает | Чините TLS/цепочку, ускоряйте |
| Симптом | Причина | Проверка/исправление |
| Бот молчит | Webhook не установлен | getWebhookInfo, TLS/200 OK |
| Двойные сообщения | offset не сдвигается | last_update_id, идемпотентность |
| Не пишет в группу | Privacy Mode/нет прав | /setprivacy, выдать админа |
| Кнопка не отвечает | Неверный callback_data | Длины/JSON, обработчик |
| Падает на медиа | Превышен размер/тип | Лимиты, fallback |
| В PM «blocked» | Пользователь заблокировал | Проверить 403, не слать повторно |
curl -F "url=https://example.com/bot-hook" https://api.telegram.org/bot<TOKEN>/setWebhook
curl https://api.telegram.org/bot<TOKEN>/getWebhookInfocurl "https://api.telegram.org/bot<TOKEN>/deleteWebhook?drop_pending_updates=true"
curl "https://api.telegram.org/bot<TOKEN>/getUpdates?timeout=30"curl -i https://example.com/bot-hook/healthТокен, команды, Privacy Mode, права в чатах. Вебхук: валидный сертификат, 200 OK, таймауты (время ожидания ответа). Лимиты, очереди, мониторинг ошибок и задержек. Задокументируйте версии, домены и режим получения апдейтов.
Остановите шторм запросов и включите бэкофф. Включите расширенный лог апдейтов и ошибок с отметкой времени. Проверьте инфраструктуру (DNS, TLS, сеть), при необходимости сделайте откат/канареечный релиз. Временно перейдите на polling до фикса вебхука.
Единый формат логов ускоряет поиск причины и сравнение релизов. Рекомендуем поля: request_id, update_id, chat_id, handler, t_start, t_finish, duration_ms, status_code, error_class, error_message, retry_count, webhook_url. Держите правило: p95 duration_ms ≤ 3000 (95% запросов быстрее 3 c). Это простая цель, которая хорошо коррелирует с «бот отвечает вовремя».
{
"request_id":"...",
"update_id":123456789,
"chat_id":-100123456,
"handler":"onCallback",
"t_start":"2025-11-14T09:00:00Z",
"t_finish":"2025-11-14T09:00:01Z",
"duration_ms":980,
"status_code":200,
"error_class":null,
"error_message":null,
"retry_count":0,
"webhook_url":"https://example.com/bot-hook"
}Поставьте алерт, если last_error_date в getWebhookInfo обновился за последние 5 минут – это ранний сигнал. Алерт на p95 duration_ms > 2000 ms 5 минут подряд – повод разбирать задержки. SLO: ≥ 99.9% успешных 200 OK вебхука и p95 < 2 s. Эти цели реалистичны и дают предсказуемое качество сервиса.
Быстро проверить цепочку сертификатов можно одной командой OpenSSL. Выполните строку ниже и посмотрите issuer/subject/dates и что цепочка полная (есть intermediate). Обратите внимание на CN/SAN (имя домена) и актуальные даты – просроченный cert «глушит» вебхук. Если chain неполный – настройте веб‑сервер на выдачу полного набора.
echo | openssl s_client -servername example.com -connect example.com:443 -showcerts 2>/dev/null | openssl x509 -noout -issuer -subject -datesПокройте редкие типы событий: poll, shipping_query, pre_checkout_query, chat_join_request. Цель проста: бот не падает на неожиданных payload (тела запросов). Добавьте заглушки и валидаторы схем, чтобы ловить несоответствия. Такой слой предотвращает «тихие» падения после обновлений клиентов.
Сделайте таблицу processed_updates(update_id PK, processed_at) или Redis‑ключи с TTL. Паттерн «check‑then‑set» гарантирует от дублей при ретраях (повторных попытках). Обработка должна быть атомарной: записали – значит обработано. Это убирает «призраков» и неожиданные повторные платежи/действия.
Вынесите в middleware: timeout, экспоненциальный backoff с jitter, max retries, короткое замыкание при 5xx/timeout. Единая политика делает поведение предсказуемым и экономит лимиты. Добавьте дружелюбные сообщения пользователю при деградации. Это повышает доверие и удержание.
Потоки вебхука: количество запросов, доля 200/не‑200, p95/avg задержка. Распределение типов апдейтов: видеть, что реально приходит и где пустоты. Ошибки по кодам: 400/401/403/409/429/5xx – понятная карта неисправностей. Очереди/рассылка: глубина, скорость обработки, отклонения от нормы.
Проверьте Privacy Mode и права: бот видит только команды? Включите/выключите по сценарию. Снимите getWebhookInfo, посмотрите last_error_message: нет ли TLS/timeout. Проверьте TLS chain/CN/SNI и переключитесь временно на polling, затем – откат/канареечный релиз. Такой порядок сокращает MTTR и исключает «гонки» каналов.
Прокси/балансировщик перезаписывает заголовок Host – SNI/маршрут ломается; явно форсируйте proxy_set_header Host ... и корректный SNI на бэкенде. Серверлесс страдает от холодного старта (>3–5 s): держите прогрев по cron. Инлайн‑режим: проверьте лимиты answerInlineQuery и кэш. MarkdownV2: экранируйте спецсимволы _[]()~ – иначе будут «тихие» 400.