Привет. Я в своей мастерской давно понял одну простую штуку: n8n умирает не от “сложности”, а от наглости. Пока один workflow таскает PDF, второй жмёт в AI, третий гоняет пачку HTTP-запросов, четвёртый лезет в Code node — инстанс делает вид, что держится, а потом внезапно превращается в тыкву. Поэтому ответ на запрос тут прямой: ограничиваем параллельность продакшн-запусков, выносим тяжёлую работу в queue mode, аккуратно крутим worker concurrency, ставим таймауты и не держим тяжёлые бинарники в памяти дольше, чем надо.
Ниже покажу, какие ручки реально работают, где народ чаще всего мажет мимо, и какой базовый набор настроек я бы поставил первым делом, если workflow уже начали душить инстанс.
Содержание:
Почему n8n начинает задыхаться под нагрузкой
Самая частая ловушка такая: человек активировал несколько workflow, подключил вебхуки, добавил крон, а дальше живёт с ощущением, что система сама как-нибудь разрулит поток. На маленьком объёме оно и правда прокатывает. Но как только одновременно прилетает пачка продакшн-запусков, начинается толкотня за CPU, RAM, event loop и внешние сервисы.
Особенно быстро жарко становится в трёх случаях. Первый — когда внутри много AI-узлов, долгих HTTP-вызовов или разборки документов. Второй — когда workflow тянет большие файлы и таскает бинарные данные по половине схемы. Третий — когда в Code node живёт жирный JavaScript или Python, который ест память и время как не в себя.
Тут важный нюанс: concurrency control в n8n касается именно production executions, то есть запусков от webhook и trigger-узлов. Ручные прогоны в редакторе, дочерние sub-workflow, error workflow и CLI-старты живут по своим правилам. Из-за этого новички часто тестируют вручную, видят одну картину, а в бою получают совсем другую. И потом сидят с лицом человека, который вроде всё “настроил”, а сервер всё равно кашляет.
Ещё один подвох — путать “много запусков” и “хорошая производительность”. Нет, братцы. Если у тебя десять тяжёлых запусков одновременно жрут один и тот же инстанс, это не ускорение. Это драка за ресурсы. В итоге растёт latency, подвисают вебхуки, ошибки сыпятся пачкой, а самые длинные сценарии добивают железо последним рывком.
Если у тебя вход идёт через вебхуки, сначала наведи порядок в защите вебхуков от повторных запросов. Иначе ты можешь идеально настроить очередь, а потом обнаружить, что она честно обрабатывает дубли и сама себе роет яму.

Три ручки, которые реально спасают инстанс
1. Глобальный лимит продакшн-запусков
Если ты сидишь в regular mode, первая ручка — это глобальный лимит параллельных production executions через переменную окружения N8N_CONCURRENCY_PRODUCTION_LIMIT. Вот она и не даёт инстансу в один момент набрать столько работы, что он сам себя уронит.
N8N_CONCURRENCY_PRODUCTION_LIMIT=3
Как я это читаю на человеческом: одновременно работает только три продакшн-экзекьюшена, всё лишнее становится в очередь и ждёт своей очереди. Для многих маленьких проектов уже этого хватает, чтобы снять острый приступ “почему всё зависает при двух-трёх параллельных клиентах”.
Стартовать обычно лучше не с красивых цифр, а с занудного минимума. Если workflow тяжёлые, я бы сначала дал лимит 2–4, посмотрел на память, время ответа, хвост очереди и уже потом добавлял. Тут нет медали за храбрость. Есть только график, который либо зелёный, либо горит.
И ещё: queued executions в n8n — это не бесконечный холодильник. Их нельзя просто взять и ретрайнуть как обычные фейлы. Если отменил или удалил такой запуск, он исчезает из очереди. Поэтому лимит нужен не ради красоты в конфиге, а ради управляемого потока.
2. Queue mode и worker concurrency
Когда regular mode уже упёрся лбом в потолок, я бы смотрел в сторону queue mode. Смысл простой: main-процесс принимает события и управляет системой, а тяжёлую работу разбирают worker’ы. То есть ты перестаёшь валить всё в одну кастрюлю и начинаешь раскладывать по конфоркам.
У worker’ов есть свой параметр параллельности — --concurrency. По умолчанию он довольно бодрый, так что оставлять дефолт на тяжёлых сценариях вслепую я бы не советовал.
n8n worker --concurrency=5
Тут есть тонкий момент. В документации n8n рекомендуют держать concurrency у worker’ов на уровне 5 и выше, потому что слишком много worker’ов с маленькой параллельностью могут начать выжигать пул соединений к базе и устроить новые тормоза уже с другой стороны. Но в реальной жизни, если у тебя workflow действительно тяжёлые по CPU или RAM, я бы не стеснялся начать с меньшей фактической нагрузки на один worker и измерить поведение. Главное — не плодить десятки worker’ов “на авось”. Сначала считаем, потом масштабируем.
Рабочая логика тут такая:
- если workflows в основном I/O-bound, можно позволить worker’у больше параллельных задач;
- если внутри много кода, AI, PDF, изображений и прочей тяжёлой кухни, лучше осторожнее;
- если очередь растёт, а CPU не забит, возможно, ты упёрся не в процессор, а в базу, Redis, внешнее API или лимиты task runner’ов.
Для быстрых стартов полезно глянуть подборку шаблонов для n8n, но тяжёлые продакшн-сценарии всё равно надо докручивать под своё железо и свой поток. Шаблон не знает, сколько у тебя памяти и как больно твоей базе, когда одновременно прилетают жирные джобы.
3. Task runners, таймауты и всё, что связано с Code node
Если у тебя в workflow живут Code node, Python или кастомная логика, не смотри на task runners как на экзотику. В новых боевых раскладах это уже вполне нормальный рабочий инструмент. В проде их разумно запускать во внешнем режиме, чтобы код исполнялся изолированно, а не внутри того же процесса, который держит всю автоматику.
На практике я смотрю сразу на три вещи:
N8N_RUNNERS_MODE=external— чтобы runner жил отдельно;N8N_RUNNERS_MAX_CONCURRENCY— чтобы runner не брал больше задач, чем реально переварит;N8N_RUNNERS_TASK_TIMEOUT— чтобы зависшая задача не висела до пенсии.
И ещё не забывай про общие таймауты workflow. Переменная EXECUTIONS_TIMEOUT задаёт дефолтный потолок по времени, а EXECUTIONS_TIMEOUT_MAX ограничивает максимум, который можно выставить на уровне конкретного workflow. Это спасает от историй, когда один подвисший сценарий занимает слот так долго, что очередь начинает пухнуть на ровном месте.
Как я настраиваю тяжёлые workflow на практике
Вот мой базовый сценарий, когда вижу, что инстанс начал работать нервно.
Сначала делю workflows на лёгкие и тяжёлые
Не надо лечить всё одной цифрой. Вебхук, который принимает заявку и пишет строку в таблицу, — это один класс нагрузки. А вот распознавание файлов, пакетная обработка данных, AI-агенты, генерация документов, жирные Code node — уже совсем другой разговор. Если мешать их в одну кучу, ты никогда нормально не поймёшь, где у тебя настоящее узкое место.
Потом режу параллельность, а не мечты
На старте я лучше переживу очередь длиной в несколько запусков, чем падение всего инстанса. Поэтому сначала ставлю жёсткий лимит, наблюдаю за системой, а уже потом двигаю цифры вверх. На проде побеждает не тот, кто запустил двадцать workflow сразу, а тот, кто стабильно обрабатывает поток без сюрпризов.
После этого убираю мусор из самих workflow
Очень часто проблема не в n8n как таковом, а в том, что workflow собран “на радостях”. Лишние узлы, дублирующиеся запросы, огромные массивы данных, передача бинарников через всю схему, отсутствие фильтрации на раннем этапе — вот тебе и печка. Я обычно делаю так:
- ставлю фильтры как можно раньше, чтобы не тащить хлам дальше по цепочке;
- большие пачки бью на этапы, а не проглатываю одним куском;
- не гоняю бинарные данные через лишние узлы;
- проверяю, где можно сохранить только нужный минимум, а не весь execution payload.
Если workflow работают с файлами, это вообще отдельная песня. По умолчанию бинарные данные могут висеть в памяти, а это отличный способ устроить себе out-of-memory на ровном месте. В regular mode обычно помогает перевод хранения бинарных данных в файловый режим. А вот в queue mode этот вариант не поддерживается — там надо смотреть в сторону хранения через базу и не забывать про pruning, чтобы хвосты старых запусков не сжирали место.
Параллельно очень советую держать под рукой схему с retries и уведомлениями об ошибках. Когда начинаешь крутить concurrency, тебе нужно быстро видеть, где именно всё ломается: во внешнем API, в коде, в таймаутах или в нехватке ресурсов.
И только потом масштабирую
Вот это место народ особенно любит перепрыгнуть. Увидели очередь — сразу добавили worker’ов. А надо бы сначала понять, что именно тормозит. Если одна задача жрёт 2 ГБ памяти и минуту CPU, то пять таких задач параллельно не сделают мир лучше. Они просто съедят всё быстрее. Масштабирование работает только после того, как у тебя есть нормальная картина по времени выполнения, памяти и точке отказа.
Грабли, на которые проще не наступать
Грабля первая: тестировать всё вручную и думать, что в бою будет то же самое. Не будет. Ручной запуск и продакшн-триггеры для concurrency control — разные истории.
Грабля вторая: включить queue mode и успокоиться. Сам по себе queue mode не лечит плохие workflow. Он просто даёт тебе более нормальную архитектуру для управления нагрузкой.
Грабля третья: выставить worker concurrency на максимум, потому что “ну так же быстрее”. Быстрее ты получишь только каскадный факап, если задачи тяжёлые.
Грабля четвёртая: поставить слишком маленькую параллельность на куче worker’ов и словить проблемы уже на пуле соединений к базе. Это особенно коварно, потому что внешне кажется, будто ты сделал всё осторожно.
Грабля пятая: забыть про Code node и task runners. Когда пользовательский код крутится не там и не так, он может очень неприятно влиять на остальной инстанс.
Грабля шестая: игнорировать execution data и pruning. Иногда сервер “умирает” не в моменте, а медленно, потому что на нём копится мусор от старых запусков, ошибок и файлов.
Чек-лист перед боем
- Поставь
N8N_CONCURRENCY_PRODUCTION_LIMITи начни с консервативного значения. - Если нагрузка выросла, переводи тяжёлые сценарии в queue mode.
- Настрой
--concurrencyу worker’ов по реальному профилю задач, а не наугад. - Для Code node и Python используй task runners во внешнем режиме.
- Задай таймауты для workflow и runner’ов.
- Не держи большие бинарники в памяти дольше, чем нужно.
- Включи pruning execution data и следи за ростом хранилища.
- Смотри не только на CPU, но и на RAM, очередь, базу, Redis и внешние API.
- Проверяй поведение именно на production triggers, а не только в ручных прогонах.
Если собрать всё в одну фразу, то мой рецепт такой: сначала зажимаем поток, потом раскладываем тяжёлые задачи по worker’ам, потом изолируем код, и только после этого думаем о масштабировании. Тогда n8n перестаёт быть капризной коробкой с проводами и начинает вести себя как нормальный рабочий станок. Не идеальный, не волшебный, а честный: сколько настроил с головой — столько и вывезет.