Платформа повторов вебхуков: пережить повторные доставки провайдера
Stripe, GitHub и Slack повторяют неудачные вебхуки часами и днями. Нужны три слоя: отсечь подделки, ACK в лимите провайдера и повтор downstream без дублирования эффектов. Inquir даёт идемпотентность, повторы пайплайна и трассировки каждой доставки.
Обновлено: 2026-06-23
Кратко
Суть ответа
Платформа повторов вебхуков: пережить повторные доставки провайдера. Функция вебхука проверяет подпись, пишет event ID провайдера в durable-хранилище, сразу возвращает 200 и ставит работу в пайплайн. Повторы провайдера упираются в idempotency-check и получают 200 без re-processing.
Когда подходит и когда нет
- Вебхуки Stripe, GitHub, Slack, Shopify, HubSpot с агрессивными retry
- Downstream может упасть после 200 провайдеру
На что обратить внимание
- Проверка «видел ли event ID?» в памяти процесса не переживает рестарт и горизонтальное масштабирование. Нужны durable-ключи идемпотентности до любого side effect.
- Повтор всего webhook-handler при сбое downstream снова гоняет верификацию подписи и рискует double-processing, если первая попытка частично успела.
Ситуация: нагрузка и где обычно ломается
Два вида повторов вебхуков — оба больно игнорировать
Повторы провайдера: Stripe до 72 часов при non-2xx или таймауте. GitHub — до 3 дней. Каждая redelivery — новый HTTP с тем же event ID; дубликаты нужно ловить до мутаций.
Повторы downstream: handler уже ответил 200, но fulfillment API упал. Без платформы повторов — тихий сбой или ручной replay из логов. Повторы шагов пайплайна решают это без re-trigger провайдера.
Компромиссы
Почему ad-hoc retry ломается в масштабе
Проверка «видел ли event ID?» в памяти процесса не переживает рестарт и горизонтальное масштабирование. Нужны durable-ключи идемпотентности до любого side effect.
Повтор всего webhook-handler при сбое downstream снова гоняет верификацию подписи и рискует double-processing, если первая попытка частично успела.
Как Inquir помогает в этом сценарии
Идемпотентный ingress + retriable-пайплайны
Функция вебхука проверяет подпись, пишет event ID провайдера в durable-хранилище, сразу возвращает 200 и ставит работу в пайплайн. Повторы провайдера упираются в idempotency-check и получают 200 без re-processing.
Шаги пайплайна повторяются независимо с exponential backoff. Трассировки показывают каждую доставку, каждый retry шага и итог — on-call отвечает «обработано ли событие?» за секунды.
Что вы получаете на платформе
Возможности платформы повторов вебхуков
Идемпотентность провайдера
Upsert event ID до мутаций. Дубликаты Stripe, GitHub, Slack — 200 без побочных эффектов.
Быстрый ACK под давлением таймаута
200 в окне Slack 3 с, лимите Stripe 30 с и ожиданиях GitHub — тяжёлое в пайплайнах.
Повторы шагов downstream
Шаги пайплайна повторяют упавшие API, записи в БД и нотификации без повторного вызова ingress-функции.
Трассировки на доставку
Заголовки, время, счётчик retry и выходы шагов для каждой доставки — не чёрный ящик воркера.
Что сделать дальше, по шагам
Как собрать платформу повторов вебхуков на Inquir
Разделите повторы провайдера (idempotency на ingress) и downstream (политика шагов пайплайна).
Проверить и записать event ID
HMAC по сырому body, upsert event ID провайдера, 200 — даже при duplicate delivery.
Поставить durable-работу
global.durable.startNew() с разобранным payload. HTTP завершается до начала downstream.
Повторять шаги, не вебхук
Политика retry на шагах пайплайна для downstream. Завершённые шаги не перезапускаются при падении следующего.
Пример кода
Идемпотентный ingress вебхука с передачей в пайплайн
Повторы провайдера — idempotency-check. Сбои downstream — retry на уровне шага пайплайна.
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 с агрессивными retry
- Downstream может упасть после 200 провайдеру
Когда лучше не трогать
- Вебхуки уходят в чужую iPaaS без своей среды выполнения
Вопросы и ответы
Вопросы и ответы
Как долго провайдеры повторяют?
Stripe: до 72 ч с backoff. GitHub: до 3 дней. Slack ждёт ответ ~3 с. Закладывайте быстрый ACK и duplicate delivery.
Если исчерпаны retry шага?
Прогон пайплайна failed с полными логами. Алерт по failure rate; ручной replay из истории по сохранённому payload.
Нужна отдельная dead-letter очередь?
Failed-прогоны пайплайна — DLQ с поиском в истории. Отдельную инфраструктуру DLQ поднимать не нужно.