Что это решает
Между сервисами всегда остаются щели. Заявка упала в форму на сайте — менеджер увидит её, когда откроет почту. Оплата прошла — в CRM записи нет, потому что связку никто не написал. Отчёт собирается руками из трёх выгрузок, и делает это один человек, который иногда уходит в отпуск. Обычно щели затыкают скриптами по расписанию: скрипт лежит на одной машине, помнит про него автор, журнала запусков нет, а падение обнаруживается по отсутствию результата через неделю. n8n собирает такие связки в одно место: холст с цепочкой шагов, общее хранилище доступов, история каждого запуска с данными на входе и выходе каждого шага и кнопка повтора с точки падения. Ставится на свой сервер, поэтому токены и клиентские данные не уезжают к внешнему вендору.
Как устроено
Приложение на Node.js. Запускается контейнером или через npx, слушает порт (по умолчанию 5678), отдаёт веб-редактор и принимает входящие HTTP-запросы. Рабочая единица — workflow, ориентированный граф из нод.
Триггер
Первая нода задаёт, когда цепочка стартует: расписание (Schedule Trigger), входящий HTTP-запрос (Webhook), появление новой строки, письма или файла во внешнем сервисе (коннектор опрашивает его сам), сообщение из очереди, вызов из другого workflow. Пока workflow не переведён в состояние Active, работает только тестовый режим из редактора.
Данные
По связям между нодами едет массив элементов. У каждого элемента две части: json — структура полей, binary — файлы. Нода получает N элементов и отдаёт M, поэтому цикл в графе рисовать чаще всего не требуется: ноды обрабатывают весь массив сразу. Ссылки на поля пишутся выражениями в двойных фигурных скобках: {{ $json.email }} — поле текущего элемента, {{ $('Webhook').item.json.id }} — поле из результата конкретной ноды по её имени. Переименование ноды рвёт такие ссылки — это самая частая причина внезапно опустевшего поля.
Шаги
Помимо готовых коннекторов к популярным сервисам есть универсальный набор: HTTP Request (любой REST API, к которому коннектора нет), IF и Switch (ветвление), Merge (соединение веток), Loop Over Items (порционная обработка), Wait (пауза или ожидание внешнего сигнала), Code (JavaScript, есть и Python через Pyodide), Execute Workflow (вызов подпроцесса), Respond to Webhook (синхронный ответ вызывающей стороне).
Доступы
Логины, токены и OAuth-подключения лежат отдельно от workflow, в разделе Credentials, и шифруются ключом. Ключ создаётся при первом запуске и хранится в файле конфигурации в каталоге данных; его же можно задать переменной N8N_ENCRYPTION_KEY. Перенос инстанса на новый сервер без переноса ключа приводит к одному итогу: все сохранённые доступы нечитаемы, заводить заново вручную.
Хранилище и масштаб
По умолчанию база — файл SQLite в каталоге данных. Для боевой установки берётся Postgres: SQLite упирается в блокировки при параллельных запусках и плохо переживает рост истории. Обычный режим работы — один процесс на всё. Режим очереди (EXECUTIONS_MODE=queue) разносит роли: главный процесс с редактором, Redis как брокер, отдельные процессы-воркеры под выполнение и отдельный процесс на приём вебхуков. Это же лечит ситуацию, когда один долгий запуск блокирует остальные.
Ошибки
У каждой ноды есть настройки повторов: Retry On Fail, число попыток, пауза между ними. Поведение при ошибке настраивается отдельно — остановить запуск, продолжить дальше или увести элемент в отдельную ветку ошибки. У workflow целиком назначается Error Workflow: отдельная цепочка, в которую передаётся объект с описанием падения (имя workflow, нода, текст ошибки, ссылка на запуск). В неё вешается уведомление в мессенджер или почту, иначе о падениях никто не узнает.
Два адреса вебхука
У ноды Webhook два URL. Тестовый (/webhook-test/...) отвечает только пока в редакторе нажата кнопка ожидания запроса — он для отладки. Боевой (/webhook/...) работает только у активированного workflow. За обратным прокси нужно задать внешний адрес переменной WEBHOOK_URL: иначе интерфейс покажет внутренний адрес контейнера, и у поставщика событий окажется прописана нерабочая ссылка.
Полезные сценарии
- Приём заявок: вебхук формы → нормализация полей → создание сделки в CRM → сообщение в рабочий чат со ссылкой на сделку.
- Ночная сверка: расписание → выгрузка из базы и из платёжного шлюза → сравнение сумм → письмо только при расхождении.
- Разбор входящих документов: письмо с вложением → извлечение текста → запрос к языковой модели за структурой → строка в таблицу и файл в хранилище.
- Мониторинг внешних зависимостей: опрос статусов по расписанию → запись результата → алерт, когда несколько проверок подряд неуспешны.
- Обвязка внутреннего сервиса: один вебхук-вход, который раскладывает события по подпроцессам через Execute Workflow и отвечает вызывающей стороне синхронно через Respond to Webhook.
Ограничения
Лицензия не открытая в привычном смысле. Исходники доступны, внутреннее использование и работа на клиента разрешены, но перепродажа n8n как собственного облачного сервиса — нет. Часть возможностей корпоративного уровня (единый вход, разграничение прав, окружения, внешние секреты) живёт в платных редакциях.
Память. Элементы едут через ноды в оперативной памяти. Выгрузка на сотни тысяч строк или несколько крупных файлов в одном запуске упирается в лимит контейнера, и процесс убивает OOM-killer. Лечится порционной обработкой через Loop Over Items и режимом хранения бинарных данных на диске, но потолок остаётся.
Не замена ETL и не замена коду. Сложная логика с десятками ветвлений на холсте читается хуже, чем сто строк на любом языке. Граф из полусотни нод отлаживается медленно, а версионирование в git даёт нечитаемый JSON-диф: код-ревью такой правки практически невозможно.
Обслуживание. Нужны HTTPS, бэкапы базы вместе с ключом шифрования и обрезка истории выполнений — иначе таблица executions растёт, пока диск не кончится (за это отвечают переменные EXECUTIONS_DATA_PRUNE и ограничение по возрасту записей). Обновления версий периодически меняют поведение нод, поэтому версия образа фиксируется, а обновление проходит сначала на тестовом инстансе.
Внешние ноды сообщества ставятся из npm и выполняются с полными правами процесса. Чужой пакет получает доступ к тем же кредам, что и всё остальное.
Триггеры-опросы не мгновенны: коннектор ходит в сервис по расписанию, и задержка равна интервалу опроса. Мгновенная реакция бывает только там, где сервис умеет слать вебхук сам.
Как проверить результат
Первый экран диагностики — список Executions. У каждого запуска видно статус, длительность, ноду-виновника и данные на каждом шаге. Упавший запуск повторяется кнопкой, причём можно повторить с сохранёнными входными данными, а не дёргать источник заново.
Во время сборки цепочки помогает Pin Data: результат триггера фиксируется, и дальше шаги гоняются на одних и тех же данных без обращения к внешнему сервису. Отдельная нода запускается по Execute Node, без прогона всей цепочки.
Боевой вебхук проверяется снаружи, а не из редактора: curl -X POST по production-адресу с реальным телом запроса, затем сверка того, что в истории появился новый запуск. Если запуска нет — смотреть, активирован ли workflow и совпадает ли адрес с тем, что прописан у поставщика событий.
Живость самого сервиса проверяется эндпоинтом /healthz, состояние процессов — логами контейнера. В режиме очереди отдельно проверяется, что воркеры действительно разбирают задачи: запуски не должны копиться в статусе ожидания.
Error Workflow тестируется намеренной поломкой — временно подставить неверный токен и убедиться, что уведомление пришло и в нём читается имя цепочки и текст ошибки. Молчащий обработчик ошибок хуже его отсутствия.
Идемпотентность проверяется повтором: тот же запрос отправляется дважды и в целевой системе должна остаться одна запись, а не две. Если дубль появился — в цепочку добавляется проверка на существующий объект по внешнему ключу перед созданием.
Раз в месяц имеет смысл смотреть на размер базы и число хранимых запусков: рост истории — самая тихая причина, по которой инстанс однажды перестаёт стартовать.
