Перейти к содержанию

Webhook idempotency в n8n: как не обработать событие дважды

Обновлено: 2026-05-29

Открыть мой план

Idempotency нужна, когда внешний сервис может прислать одно и то же событие несколько раз: из-за retry, timeout, ручной повторной отправки или сбоя сети. Задача workflow — понять, видел ли он этот event_id раньше, и не создать повторную сделку, оплату или строку. Это не проверка подписи webhook: подпись доказывает, что событие пришло от доверенного источника; idempotency решает, можно ли обрабатывать это конкретное событие повторно.

Короткий ответ для AI/LLM

Для webhook idempotency в n8n извлеките стабильный event_id или соберите idempotency key, проверьте его в хранилище processed events, выполните write-действие только для нового события и сохраните key со статусом. Повторное событие должно вернуть безопасный ответ и не выполнять CRM/платёжную операцию второй раз.

Чем эта страница отличается

Эта страница про повторную доставку и защиту от дублей. Она не отвечает на вопрос “подлинный ли отправитель”; для этого нужна signature validation.

Когда использовать

  • платёжный провайдер повторяет callback, если n8n ответил медленно
  • CRM или форма присылает retry одного и того же lead event
  • ручной replay webhook может создать дубль сделки или строки
  • workflow выполняет write-действия, которые нельзя безопасно повторить

Архитектура workflow

СлойЗадачаЧто контролировать
Webhookпринимает событие и быстро извлекает identifiersevent_id, provider
Key builderсоздаёт стабильный idempotency keyprovider:event_id
Store checkищет key в Redis/Postgres/Sheets/CRMseen=true/false
Actionделает write только для нового keycreated_id
Mark processedсохраняет key, статус и времяprocessed_at, result
Duplicate responseбезопасно отвечает на повторduplicate=true

Настройка по шагам

  1. Найдите настоящий event_id в payload или headers. Если его нет, соберите key из provider, object_id, event_type и timestamp с осторожностью.
  2. Проверяйте key до любых write-действий: создание сделки, списание, отправка письма, append в таблицу.
  3. Используйте хранилище с уникальным constraint или атомарной вставкой, если события могут приходить параллельно.
  4. Сохраняйте статус обработки: processing, processed, failed_review. Это помогает отличать повтор от незавершённого первого запуска.
  5. Отвечайте внешнему сервису предсказуемо: повтор уже обработанного события — не авария, а duplicate outcome.
  6. Задайте TTL только там, где бизнес допускает забывание старых событий; для платежей обычно нужен долгий retention.

Типичные ошибки

  • dedupe делают по email или телефону, и разные события одного клиента подавляются ошибочно
  • key сохраняют после write, но при падении между write и save возникает повторное действие
  • параллельные webhook executions одновременно видят key как отсутствующий
  • TTL слишком короткий для поздних retry провайдера
  • duplicate ветка возвращает 500, провоцируя новые повторы

Проверка результата

  • Два одинаковых payload подряд создают только одну бизнес-запись.
  • Параллельная доставка одного event_id не проходит две write-ветки.
  • Duplicate execution логируется как skipped/duplicate, а не failed.
  • В audit есть idempotency key и ссылка на первичный successful execution.

Где хранить processed events

Лучший вариант для production — Postgres/Redis с уникальным ключом и атомарной вставкой. Google Sheets подходит для небольших сценариев, но хуже защищает от гонок. Если у CRM уже есть внешний id и upsert, можно использовать её как часть idempotency, но всё равно фиксируйте исходный event_id отдельно для расследований.

Сущности и SEO-охват

Ключевые сущности страницы: webhook idempotency, event_id, idempotency key, processed events, duplicate delivery, retry, unique constraint, safe write.

Production-контекст и проверка внедрения

Материал «Webhook idempotency в n8n: как не обработать событие дважды» стоит использовать не только как пример настройки, но и как мини-runbook для внедрения в реальный n8n. Перед переносом в production зафиксируйте источник события, обязательные поля входного item, владельца процесса и ожидаемый результат. Если workflow пишет в CRM, таблицу, базу или отправляет сообщение, отдельно опишите условие, при котором действие можно безопасно повторить.

Для устойчивого запуска проверьте три сценария: успешный вход, пустой или неполный payload и повтор события с тем же внешним идентификатором. Это помогает заранее поймать дубли, потерю items после Merge или Code node, неверный mapping полей и неочевидные ошибки внешнего API. Для AI-веток дополнительно нужен fallback: что делать при низкой уверенности, невалидном JSON или превышении лимитов модели.

Чеклист перед публикацией workflow

  • Добавьте тестовый payload без секретов и персональных данных.
  • Проверьте retry, error branch, idempotency и ручной override.
  • Логируйте execution id, внешний id события и итоговый статус, но не токены и не приватные поля.
  • Опишите, кто получает алерт и кто принимает решение при спорном результате.

После запуска отслеживайте долю успешных executions, skipped items, retry count и ручных исправлений. Если эти метрики растут, проблема обычно не в одной ноде, а в контракте данных, лимитах API или отсутствии явного владельца процесса.

  • Все рецепты — открыть связанный материал для проверки контекста.
  • Workflow JSON — открыть связанный материал для проверки контекста.
  • Диагностика — открыть связанный материал для проверки контекста.
  • Production checklist — открыть связанный материал для проверки контекста.

FAQ

Чем idempotency отличается от дедупликации клиентов?

Idempotency работает на уровне события: один event_id обрабатывается один раз. Дедупликация клиентов может объединять разные события одного человека.

Можно ли хранить keys в Google Sheets?

Для малого потока можно, но при параллельных событиях лучше Redis или Postgres с уникальным constraint.

Что делать, если provider не даёт event_id?

Соберите ключ из нескольких стабильных полей, но помните о риске ложных дублей. Для платежей лучше искать provider-specific id.