Оптовая платформа цифровых товаров

Webhook failure recovery 2026: паттерны для B2B API цифровых товаров

Боевые паттерны восстановления webhook-доставки: математика backoff, DLQ, идемпотентность и SLA-алёрты.

Webhook failure recovery 2026: паттерны для B2B API цифровых товаров

Webhook-доставка в B2B-интеграциях цифровых товаров — это критичный путь: пропущенное событие order.delivered означает, что код карты не уходит клиенту, и поддержка завалена тикетами. В этой статье — production-паттерны, которые мы видим у топовых FoxReload-партнёров с uptime 99.95%+.

1. Exponential backoff с jitter — математика

Простой ретрай каждые 30 секунд убивает ваш receiver при инциденте на нашей стороне (thundering herd). Правильная формула:

function nextRetryDelay(attempt: number): number {
  const base = 30_000; // 30s
  const cap = 6 * 60 * 60 * 1000; // 6h
  const exp = Math.min(base * Math.pow(2, attempt), cap);
  const jitter = Math.random() * exp * 0.3; // ±30%
  return exp + jitter;
}

FoxReload применяет именно этот алгоритм: попытки 1–8 распределяются в окне 30s → 24h. Caps на 6 часах не дают одному webhook занять воркер навсегда, а jitter ±30% размазывает retry-пики по времени.

2. Dead-letter queue (DLQ)

После 8 неудачных попыток событие должно попадать в DLQ, а не теряться. Production-паттерн — отдельная очередь с manual replay:

// Express + BullMQ
app.post('/webhook/foxreload', async (req, res) => {
  const sig = req.header('X-Foxreload-Signature');
  if (!verifyHmac(req.rawBody, sig, process.env.WEBHOOK_SECRET)) {
    return res.sendStatus(401);
  }
  const eventId = req.header('X-Foxreload-Event-Id');
  const dup = await redis.set(`evt:${eventId}`, '1', 'EX', 86400, 'NX');
  if (!dup) return res.sendStatus(200); // already processed
  await queue.add('process-event', req.body, {
    attempts: 8,
    backoff: { type: 'exponential', delay: 30000 },
    removeOnFail: false, // keep for DLQ inspection
  });
  res.sendStatus(200);
});

DLQ-события разбирает on-call инженер: либо replay через POST /v1/webhooks/{id}/replay, либо ручное закрытие заказа в админке.

3. Idempotency keys — обязательно

Webhook-доставка — at-least-once, не exactly-once. Без идемпотентности один и тот же order.delivered может списать остаток дважды. Используйте X-Foxreload-Event-Id как natural idempotency key:

Storage Latency TTL Cost / 1M events
Redis SETNX <2ms 24h $0.40
Postgres UNIQUE index 5–8ms forever $0.10
DynamoDB ConditionExpression 8–12ms 24h $1.25

Для большинства партнёров Redis SETNX оптимален: дёшево, быстро, TTL покрывает retry-окно FoxReload (24h).

4. Alerting на >1% loss

Метрика, которую вы обязаны мониторить: rolling 5-минутный success rate webhook-доставки. Если падает ниже 99% — это incident. Prometheus-правило:

- alert: WebhookDeliveryDegraded
  expr: |
    (sum(rate(webhook_received_total[5m]))
     - sum(rate(webhook_failed_total[5m])))
    / sum(rate(webhook_received_total[5m])) < 0.99
  for: 2m
  labels: { severity: page }

Алёрт идёт в PagerDuty/Opsgenie, on-call смотрит DLQ и логи. В 80% случаев причина — деплой receiver-сервиса с регрессией: rollback решает за 5 минут.

CTA

Полная webhook-документация FoxReload, replay-эндпоинты и Prometheus-метрики доступны после онбординга — запросите доступ к API.

Часто задаваемые вопросы

Сколько раз FoxReload ретраит webhook?
До 8 попыток в течение 24 часов: 30s, 1m, 5m, 30m, 2h, 6h, 12h, 24h. После 8-й — событие попадает в ваш DLQ-эндпоинт (если настроен) и помечается delivery_failed=true в admin-логе.
Как защититься от дублей webhook?
FoxReload отправляет уникальный X-Foxreload-Event-Id (UUIDv4) в каждом запросе. Сохраняйте его в Redis с TTL 24h; перед обработкой проверяйте SETNX event_id 1. Если ключ уже существует — это retry, верните 200 без побочных эффектов.
Какой timeout должен быть на receiver-эндпоинте?
Принимайте webhook за <2 секунды (FoxReload ждёт 10s, но мы рекомендуем reply-fast/work-async). Сохраните payload в очередь (SQS, Redis Streams, BullMQ) и сразу верните 200. Тяжёлую логику запускайте воркерами.
Как мониторить health webhook-доставки?
Считайте rolling 5-минутный success rate. Если падает <99% — pager. FoxReload экспонирует GET /v1/webhooks/stats с p50/p95/p99 latency и failure rate за последние 24h. Подключите его в Prometheus через blackbox-exporter.
Получить доступ к FoxReload API

Похожие статьи