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

Event-driven архитектура на n8n: как строить автоматизации вокруг событий

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

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

Короткий ответ

Event-driven архитектура в n8n означает, что workflow запускается не по ручному расписанию, а по факту события: новый webhook, сообщение из очереди, изменение в CRM, поступивший платёж, письмо, тикет или сигнал от другого сервиса. В production такой подход требует не только trigger node, но и контракта события, idempotency key, журналирования, retry/DLQ, контроля порядка обработки и безопасного replay. Если этого нет, один и тот же webhook может создать два лида, платёж может пройти без обновления CRM, а ошибка в downstream API превратится в потерянное событие.

Когда event-driven подход действительно нужен

Event-driven модель стоит использовать, когда действие должно произойти сразу после внешнего события: клиент оплатил заказ, пользователь отправил форму, менеджер поменял статус сделки, партнёр прислал webhook, поддержка получила новый тикет, AI-agent запросил выполнение tool, склад обновил остатки. В таких сценариях расписание вроде “каждые 10 минут проверять API” часто создаёт задержку, лишнюю нагрузку и сложный код сравнения состояний.

Но event-driven подход не нужен везде. Если источник не умеет отправлять события, данные можно безопасно забирать батчем, задержка в 15–60 минут допустима, а порядок обработки важнее мгновенности, cron workflow может быть проще и надёжнее. Хорошее правило: событие должно иметь понятную бизнес-ценность, стабильный идентификатор и понятный lifecycle. Если событие невозможно отличить от дубля, сначала проектируют контракт, а не запускают Webhook node.

Базовая схема event-driven workflow

Минимальная схема в n8n выглядит так: trigger принимает событие, validation node проверяет payload, normalization layer приводит поля к внутреннему формату, idempotency check решает, обрабатывали ли событие раньше, бизнес-ветка выполняет действие, audit log фиксирует результат, а error branch отправляет событие в quarantine или DLQ.

Для webhook-сценария это может быть цепочка: Webhook → Code “validate event” → Postgres “insert idempotency key” → Switch по типу события → CRM/Payments/Email nodes → Audit log → Respond to Webhook. Для очереди: queue consumer или polling node → validation → dedupe → worker workflow → status update. Для email/ticket сценариев: trigger → extraction/classification → routing → human review → update source system.

Главная мысль: event-driven workflow не должен сразу “делать полезное действие”. Сначала он должен понять, что пришло, можно ли этому верить, не было ли этого раньше, и есть ли достаточно данных для безопасного выполнения.

Контракт события

Контракт события — это договор между источником и n8n. Он отвечает на вопросы: кто отправляет событие, какой у него тип, как найти уникальный идентификатор, в какой версии формат payload, какие поля обязательны, какие поля могут отсутствовать, как обрабатывать повторную доставку.

Практичный event envelope может выглядеть так:

{
  "event_id": "evt_2026_05_29_000123",
  "event_type": "payment.succeeded",
  "event_version": "v1",
  "occurred_at": "2026-05-29T10:15:30Z",
  "source": "checkout",
  "tenant_id": "ru-shop-01",
  "correlation_id": "ord_98431",
  "payload": {
    "order_id": "98431",
    "amount": 4900,
    "currency": "RUB",
    "customer_email": "buyer@example.com"
  }
}

Если внешний сервис не даёт такой envelope, его создают на первом шаге workflow. Например, event_id можно собрать из source + external_id + status + occurred_at, а correlation_id привязать к заказу, лиду, тикету или платежу. Это резко упрощает логи, поддержку, replay и расследование инцидентов.

Идемпотентность и повторная доставка

Многие webhook-и и очереди доставляют событие повторно: из-за timeout, 500-ответа, сетевой ошибки, ручного replay, повторного сохранения формы или сбоя у провайдера. Поэтому event-driven workflow должен быть идемпотентным: повторная обработка того же события не должна создавать второй заказ, второй лид, второй платёжный статус или второе письмо клиенту.

В n8n это обычно делают через отдельное хранилище: Postgres, Redis, Data Table или внешний backend. Первый шаг после validation пытается записать idempotency_key. Если ключ уже есть со статусом processed, workflow завершает работу безопасным ответом. Если ключ есть со статусом processing и не истёк lock timeout, workflow не запускает бизнес-действие второй раз. Если ключ есть со статусом failed, запускается controlled replay.

Пример SQL-идеи:

insert into event_log (idempotency_key, event_type, status, received_at)
values (:key, :type, 'processing', now())
on conflict (idempotency_key) do nothing;

После этого workflow проверяет, была ли вставка успешной. Это простое место часто отделяет production-архитектуру от “вроде работает на тесте”.

Порядок событий и late events

Не все события приходят в правильном порядке. CRM может сначала прислать deal.updated, потом deal.created; платёжный сервис может повторно отправить старый статус; webhook из формы может приехать раньше, чем файл стал доступен по URL. Поэтому нельзя слепо применять каждое событие к текущему состоянию.

Для важных объектов храните object_version, occurred_at, status_priority или state_machine. Например, если заказ уже в статусе paid, событие payment.pending, пришедшее позже, не должно откатывать статус назад. Если сделка уже закрыта, старый webhook с qualified не должен снова открывать её.

В n8n это можно реализовать через Postgres lookup перед update: достать текущий статус, сравнить timestamp и допустимый переход, затем выполнить update только если переход валиден. Для малых проектов достаточно Switch node + Code node, но для платежей, логистики и CRM лучше описать state machine явно.

Retry, DLQ и replay

Retry нужен для временных ошибок: 429, 502, 503, timeout, сетевой сбой. DLQ нужен для событий, которые нельзя безопасно обработать сейчас: невалидный payload, неизвестный event_type, отсутствующий customer_id, запрещённый статус, ошибка прав доступа. Replay нужен, чтобы после исправления причины обработать событие заново без ручного копирования JSON из логов.

В event-driven workflow важно разделять ошибки на классы. Временная ошибка API — retry с backoff. Ошибка контракта — quarantine с причиной. Бизнес-конфликт — manual review. Неизвестный статус — DLQ и алерт владельцу интеграции.

Хороший DLQ-запись содержит исходный payload, normalized payload, idempotency key, correlation ID, error code, error message, workflow version, node name, retry count и решение: retryable, needs_mapping, needs_manual_review, discarded. Без этих полей replay превращается в гадание.

Что логировать

Минимальный production log для event-driven n8n: event_id, event_type, idempotency_key, correlation_id, source, workflow_id, workflow_version, execution_id, received_at, started_at, finished_at, status, external_object_id, retry_count, error_code. Для PII храните masked value или hash, а не полный email/телефон, если это не нужно для расследования.

Событие должно быть видно как цепочка: получено → проверено → принято/дубль/отклонено → действие выполнено → внешний объект обновлён → ответ отправлен. Если в логах виден только финальный node error, поддержка не сможет понять, потерялось ли событие, было ли оно дублем, или downstream API отклонил запрос.

Production-чеклист

Перед запуском event-driven workflow проверьте: Production URL используется вместо Test URL; источник умеет повторную доставку или вы сами храните raw payload; все события имеют idempotency key; невалидный payload не ломает workflow; 429/5xx идут в retry; unknown event type идёт в DLQ; ручной replay не создаёт дублей; Respond to Webhook возвращает понятный статус; secrets не попадают в execution data; есть owner и runbook; alert срабатывает не на каждый дубль, а на реальные сбои.

Отдельно протестируйте три сценария: один и тот же webhook два раза подряд, событие со старым статусом после нового, и сбой CRM/API после успешного idempotency insert. Эти тесты быстро показывают, готова ли архитектура к production.

Частые ошибки

  • Обрабатывать событие до validation/idempotency check.
  • Не различать duplicate, retryable failure и bad payload.
  • Не хранить raw event для replay.
  • Не защищаться от late events и старых статусов.
  • Считать webhook delivery равно business success.

Минимальный набор внутренних ссылок

  • /architecture/data-contracts/ — для описания входов и выходов workflow.
  • /architecture/idempotency-keys/ — для защиты от дублей и replay.
  • /architecture/retries-and-dlq/ — для повторов, quarantine и controlled replay.
  • /architecture/observability-metrics/ — для логов, метрик и alerting.
  • /playbooks/production-release-checklist/ — для релиза и smoke tests.

FAQ

Можно ли делать event-driven архитектуру только на Webhook node?

Можно, если источник стабильно отправляет события и нагрузка небольшая. Но для production обычно нужны validation, idempotency store, audit log, retry/DLQ и отдельный error workflow.

Нужно ли отвечать webhook сразу или после всей обработки?

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

Что делать, если событие пришло без event_id?

Соберите idempotency key из доступных стабильных полей: source, object_id, event_type, status, timestamp или hash payload. Главное — документировать правило и использовать его одинаково.

Как понять, что событие потерялось?

Нужен event log с received/processed/failed статусами и мониторингом: количество полученных событий, доля failed, возраст oldest unprocessed event, DLQ size, retry count.

Event-driven подход лучше cron workflow?

Не всегда. Event-driven лучше для быстрых реакций и внешних сигналов. Cron проще для регулярной сверки, backfill, отчётов и источников без webhooks.