Webhook не является гарантией единственной и мгновенной доставки: запрос может потеряться, получить timeout или повториться. Поэтому синхронизация должна уметь принять повтор и периодически сверять итоговое состояние через API.

Найдите событие у отправителя, проверьте журнал входящих запросов и выполните безопасную повторную обработку по event_id. Затем добавьте reconciliation, чтобы единичный потерянный webhook не оставлял данные навсегда разными.

Коротко: что сделать

  • Проверить event_id и время у отправителя
  • Проверить HTTP-логи и код ответа
  • Проверить подпись и timestamp
  • Проверить очередь и dead-letter
  • Сравнить итоговый объект через API источника

Почему возникает проблема

Событие может дойти до прокси, но не до приложения, либо приложение может сохранить данные и вернуть timeout. Оба случая требуют журналирования и идемпотентности.

  • Endpoint был недоступен во время отправки
  • Прокси ограничил body или timeout
  • Проверка подписи использует измененное тело
  • Приложение вернуло 500 после частичной записи
  • Retry отключен или слишком короткий
  • Событие попало в DLQ без оповещения

Пошаговая диагностика

Проверку лучше проводить на одном воспроизводимом примере и фиксировать результат каждого шага. Так можно быстро отделить первопричину от побочных ошибок и не менять несколько компонентов одновременно.

  • Проследить event_id через proxy, app и queue logs
  • Сверить raw body до JSON-разбора
  • Проверить правила retry отправителя
  • Проверить обработку неуспешных HTTP-кодов
  • Повторить событие в тестовой среде
  • Сравнить локальную запись с API источника

Как исправить

Endpoint должен быстро подтвердить прием после надежной записи события, а бизнес-обработку выполнять асинхронно и идемпотентно.

  • Сохранять raw event и event_id до обработки
  • Проверять подпись по исходному телу
  • Отвечать 2xx только после надежного приема
  • Обрабатывать событие через очередь с retries и DLQ
  • Добавить уникальный индекс event_id
  • Запустить периодическую reconciliation по измененным объектам

Как проверить результат

  • Отправить одно событие повторно
  • Смоделировать timeout после приема
  • Смоделировать недоступность worker
  • Проверить оповещение по DLQ
  • Убедиться, что сверка восстанавливает пропущенное состояние

Как не допустить повторения

Надежная интеграция предполагает, что webhook может быть потерян, задержан или повторен.

  • Хранить event log с ограниченным сроком
  • Мониторить задержку и процент ошибок
  • Иметь безопасную кнопку replay
  • Проводить регулярную сверку состояния

Чего не стоит делать

  • Не выполнять тяжелую обработку до HTTP-ответа
  • Не принимать webhook без проверки подписи
  • Не считать порядок доставки гарантированным
  • Не делать ручной replay без идемпотентности

Что подготовить для диагностики

  • Event ID и время
  • HTTP-коды отправки
  • Raw body и заголовки без секретов
  • Логи endpoint и worker
  • Описание API для сверки

Частые вопросы

Можно ли гарантировать, что webhook не потеряется?

Абсолютно — нет. Надежность достигается retries, журналом и сверкой состояния.

Когда возвращать 200?

После проверки запроса и надежной фиксации события, но до длительной бизнес-обработки.

Зачем event_id?

Он позволяет распознать повтор и безопасно переиграть событие без двойного результата.

Когда стоит обратиться за помощью

Обратитесь за помощью, если события влияют на оплату, статусы заказов или доступ клиентов и нужно восстановить пропуски без создания дублей.

Итог

Webhook нужно дополнять журналом, очередью, идемпотентностью и сверкой через API. Построить или восстановить такую интеграцию можно через @rabotator_support.