Как построить надёжный webhook-процессор

Webhook-эндпоинт написать легко, а надёжный процессор — это уже архитектура. Разбираем ключевые паттерны: проверку подписи, быстрое подтверждение, идемпотентность, повторные попытки и асинхронную обработку.

Как построить надёжный webhook-процессор

Сначала webhook-процессор кажется простым. Сервис отправляет HTTP-запрос. Ваш эндпоинт его получает. Вы выполняете какой-то код.

В продакшене с webhook всё сложнее.

Провайдеры повторяют неудавшиеся события. Запросы могут приходить более одного раза. События могут приходить не по порядку. Одни провайдеры требуют быстрого ответа. Другие — проверки подписи. А ваша собственная обработка может упасть на полпути.

Надёжный webhook-процессор — это не просто эндпоинт. Это небольшая система обработки событий.

Базовый поток webhook

Типичный поток обработки webhook выглядит так:

provider → webhook endpoint → verify → store event → process → update system

Например, Stripe может прислать событие об оплате, GitHub — событие о репозитории, Slack — команду, а CRM — обновление контакта.

Эндпоинт — это лишь точка входа. Настоящая работа — всё, что происходит после того, как запрос пришёл.

Паттерн 1: проверяйте запрос

Большинство серьёзных провайдеров поддерживают подпись запросов. Прежде чем доверять payload, следует проверить подпись.

Проверка обычно защищает от:

  • поддельных событий;
  • изменённого payload;
  • случайного злоупотребления публичным эндпоинтом;
  • неверной конфигурации провайдера.

Webhook-эндпоинт должен отклонять невалидные подписи до того, как начнёт какую-либо работу.

Паттерн 2: отвечайте быстро

Многие webhook-провайдеры ожидают быстрый ответ. Если ваш обработчик выполняет медленную работу до того, как вернёт ответ, вы повышаете вероятность таймаута и повторных доставок-дубликатов.

Более безопасный паттерн такой:

receive webhook
→ verify signature
→ store event or enqueue job
→ return 200 quickly
→ process asynchronously

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

Паттерн 3: делайте обработку идемпотентной

Webhook-провайдеры могут прислать одно и то же событие несколько раз. Ваш процессор должен безопасно обрабатывать дубликаты.

Например, событие об оплате не должно создавать два счёта только потому, что webhook был доставлен повторно.

Обычный подход — хранить ID события от провайдера:

event_id: evt_123
processed: true
processed_at: 2026-04-24T10:00:00Z

Перед обработкой события проверьте, не было ли оно уже обработано. Если было — верните успех, не повторяя побочные эффекты.

Паттерн 4: отделяйте подтверждение от работы

Не считайте ответ провайдеру доказательством того, что ваш бизнес-процесс завершён.

Ответ 200 OK обычно означает:

we received the event

Но он не обязательно означает:

we completed all downstream processing

Эта последующая обработка может включать запись в базу данных, вызовы API, письма, генерацию файлов, AI-суммаризацию или уведомления. Всё это часто стоит выполнять в фоновой задаче.

Паттерн 5: логируйте по ID события

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

У вас должна быть возможность искать по:

  • провайдеру;
  • типу события;
  • ID события;
  • статусу;
  • длительности обработки;
  • коду ошибки;
  • количеству повторных попыток.

Когда клиент говорит «я заплатил, но ничего не произошло», вам нужно найти конкретное событие об оплате и посмотреть, что с ним сделала ваша система.

Паттерн 6: аккуратно обрабатывайте порядок событий

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

Например:

customer.updated
subscription.created
invoice.paid

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

Паттерн 7: проектируйте с учётом повторных попыток

Есть два вида повторных попыток:

  1. повторные попытки провайдера, когда ваш эндпоинт падает;
  2. внутренние повторные попытки, когда падает ваша обработка.

Их следует обрабатывать раздельно.

Webhook-эндпоинт может вернуть 200 после сохранения события, даже если внутренняя обработка позже упадёт. Тогда ваша внутренняя система задач сможет повторить обработку, не прося провайдера присылать событие заново.

Примеры для конкретных провайдеров

Stripe

Webhook-процессор для Stripe должен проверять подпись сырого тела запроса, сохранять event.id, избегать повторной обработки и быстро отвечать. Выполнение заказа может продолжаться асинхронно.

GitHub

Webhook-обработчик для GitHub должен проверять подпись, ветвиться по типу события и не выполнять тяжёлую работу по CI или индексации внутри запроса.

Slack

Команды Slack часто требуют быстрого ответа. Медленную AI-обработку стоит вынести в фоновую задачу, а итоговый результат отправить позже.

Где здесь Inquir Compute

Inquir Compute может размещать webhook-процессоры в виде API-роутов и выносить медленную работу в фоновые задачи или пайплайны.

Архитектура webhook может выглядеть так:

/webhooks/stripe
→ verify event
→ store event ID
→ start background job
→ return 200

job: fulfill-order
→ update database
→ call external APIs
→ send notification
→ log result

Так вы не держите запрос провайдера открытым и при этом сохраняете наблюдаемость работы.

Когда достаточно простого webhook-эндпоинта

Простого эндпоинта может быть достаточно, если:

  • действие выполняется быстро;
  • дубликаты событий безвредны;
  • провайдер некритичен;
  • webhook внутренний;
  • сбои не влияют на пользователей.

Но для платежей, изменений в аккаунтах, провижининга, уведомлений или автоматизации надёжность важна.

Чеклист webhook-процессора

Прежде чем выкатывать webhook-эндпоинт, проверьте:

  • Проверяется ли запрос?
  • Есть ли ключ идемпотентности?
  • Быстро ли отвечает обработчик?
  • Логируются ли события по ID события от провайдера?
  • Можно ли безопасно повторить обработку?
  • Видны ли сбои?
  • Безопасно ли хранятся секреты?
  • Вынесена ли медленная работа в задачу?

Заключение

Надёжная обработка webhook — это управление неопределённостью.

События могут прийти дважды. Внешние API могут отказать. Провайдеры могут повторять доставку. Пользователи могут ждать результата сразу. Ваша система должна быстро подтверждать приём, безопасно обрабатывать и хранить достаточно контекста, чтобы отлаживать сбои.

Webhook-эндпоинт — это просто. Надёжный webhook-процессор — это архитектура.