Платформа повторов вебхуков: пережить повторные доставки провайдера
Stripe, GitHub и Slack повторяют неудачные вебхуки часами и днями. Нужны три слоя: отсечь подделки, подтвердить в лимите провайдера и повторить downstream-работу без дублирования эффектов. Inquir даёт идемпотентность, ретраи пайплайна и трассировки каждой доставки.
Обновлено: 2026-06-28
Кратко
Суть ответа
Платформа повторов вебхуков: пережить повторные доставки провайдера. Функция вебхука проверяет подпись, пишет event ID провайдера в durable-хранилище, сразу возвращает 200 и ставит работу в пайплайн. Повторы провайдера упираются в idempotency-check и получают 200 без re-processing.
Когда подходит и когда нет
- Вебхуки Stripe, GitHub, Slack, Shopify или HubSpot с агрессивными политиками повторных доставок
- Downstream-работа может упасть уже после того, как провайдеру ответили 200
На что обратить внимание
- Проверка «видел ли я этот event ID?» в памяти процесса не переживает рестарт и горизонтальное масштабирование. Нужны durable-ключи идемпотентности, записанные до любого побочного эффекта.
- Повтор всего webhook-handler при сбое downstream снова гоняет верификацию подписи и рискует double-processing, если первая попытка частично успела.
Ситуация: нагрузка и где обычно ломается
Два вида повторов вебхуков — оба больно игнорировать
Повторы провайдера: Stripe до 72 часов при non-2xx или таймауте. GitHub — до 3 дней. Каждая redelivery — новый HTTP с тем же event ID; дубликаты нужно ловить до мутаций.
Ретраи downstream: хендлер уже ответил 200, но fulfillment API упал. Без платформы повторов это тихий сбой или ручной replay из логов. Ретраи шагов пайплайна решают это без повторного вызова со стороны провайдера.
Компромиссы
Почему самописные ретраи ломаются в масштабе
Проверка «видел ли я этот event ID?» в памяти процесса не переживает рестарт и горизонтальное масштабирование. Нужны durable-ключи идемпотентности, записанные до любого побочного эффекта.
Повтор всего webhook-handler при сбое downstream снова гоняет верификацию подписи и рискует double-processing, если первая попытка частично успела.
Как Inquir помогает в этом сценарии
Идемпотентный ingress + retriable-пайплайны
Функция вебхука проверяет подпись, пишет event ID провайдера в durable-хранилище, сразу возвращает 200 и ставит работу в пайплайн. Повторы провайдера упираются в idempotency-check и получают 200 без re-processing.
Шаги пайплайна повторяются независимо с exponential backoff. Трассировки показывают каждую доставку, каждый ретрай шага и итог — дежурный отвечает на вопрос «обработано ли событие?» за секунды.
Что вы получаете на платформе
Возможности платформы повторов вебхуков
Идемпотентность провайдера
Upsert event ID до мутаций. Дубликаты Stripe, GitHub, Slack — 200 без побочных эффектов.
Быстрый ACK под давлением таймаута
200 в окне Slack 3 с, лимите Stripe 30 с и ожиданиях GitHub — тяжёлое в пайплайнах.
Ретраи шагов downstream
Шаги пайплайна повторяют упавшие вызовы API, записи в БД и нотификации без повторного вызова ingress-функции.
Трассировки на доставку
Заголовки, тайминги, число ретраев и выходы шагов для каждой доставки — не чёрный ящик воркера.
Что сделать дальше, по шагам
Как собрать платформу повторов вебхуков на Inquir
Разделите повторные доставки провайдера (идемпотентность на ingress) и ретраи downstream (политика шагов пайплайна).
Проверить и записать event ID
HMAC по сырому body, upsert event ID провайдера, 200 — даже при duplicate delivery.
Поставить durable-работу
global.durable.startNew() с разобранным payload. HTTP завершается до начала downstream.
Повторять шаги, а не вебхук
Настройте политику ретраев на шагах пайплайна для downstream-сбоев. Завершённые шаги не перезапускаются при падении следующего.
Пример кода
Идемпотентный ingress вебхука с передачей в пайплайн
Повторные доставки провайдера упираются в проверку идемпотентности. Сбои downstream повторяются на уровне шага пайплайна.
export async function handler(event) { const rawBody = event.body ?? ''; if (!verifyStripeSignature(rawBody, event.headers['stripe-signature'])) { return { statusCode: 400, body: 'invalid signature' }; } const evt = JSON.parse(rawBody); const isNew = await db.tryInsertWebhookEvent(evt.id, evt.type); if (!isNew) return { statusCode: 200, body: 'already processed' }; await global.durable.startNew('stripe-fulfillment', undefined, { eventId: evt.id, type: evt.type, object: evt.data.object, }); return { statusCode: 200, body: 'accepted' }; }
Когда подходит и когда нет
Когда нужна платформа повторов вебхуков
Когда это уместно
- Вебхуки Stripe, GitHub, Slack, Shopify или HubSpot с агрессивными политиками повторных доставок
- Downstream-работа может упасть уже после того, как провайдеру ответили 200
Когда лучше выбрать другое
- Вебхуки уходят в чужую iPaaS без своей среды выполнения
Вопросы и ответы
Вопросы и ответы
Как долго провайдеры повторяют?
Stripe: до 72 ч с backoff. GitHub: до 3 дней. Slack ждёт ответ ~3 с. Закладывайте быстрый ACK и duplicate delivery.
Что, если шаг исчерпал ретраи?
Прогон пайплайна помечается failed с полными логами. Настройте алерт по failure rate и делайте ручной replay из истории по сохранённому payload.
Нужна отдельная dead-letter очередь?
Failed-прогоны пайплайна — DLQ с поиском в истории. Отдельную инфраструктуру DLQ поднимать не нужно.