We upgraded our n8n setup from version 0.198 to 1.77 and later to 1.84 using Docker. We had some complex workflows (around 250+ nodes) running fine on 0.198. There are many if else and function item nodes. After the upgrade, we decided not to do an in-place upgrade but instead:
Set up a fresh instance with PostgreSQL instead of MySQL.
Replaced deprecated nodes like function/functionItem with the new code node.
Adjusted all breaking changes manually.
Set all the environment variables as listed below.
The setup works well for smaller workflows – we can send webhooks and receive the expected responses. However, when we try to use more complex workflows:
The n8n UI becomes unresponsive (Chrome shows “Page Unresponsive” errors).
Clicking on nodes does not respond, especially in large workflows.
When opened in a new tab, n8n works again, indicating this might be a client-side CPU issue.
I observed in the codebase that fetching parent and child nodes for complex workflows adds significant load to the frontend.
We also experienced backend issues:
When we try to execute those complex workflows, Docker pods start restarting, despite not hitting visible CPU/memory limits.
It seems n8n becomes unresponsive and fails health checks, leading to restarts.
To solve this, we tried:
Switching to Queue mode with Redis.
Enabling Runner mode (N8N_RUNNERS_ENABLED=true and N8N_RUNNERS_MODE=internal).
Still, the problem persists. Worker pods become unresponsive, and workflows never finish.
We considered simplifying workflows but this doesn’t align with our future plans – we expect workflows to get even more complex, and need n8n to handle them reliably.
Are there any possible improvements, configuration tweaks, or overlooked areas we should investigate to make complex workflows stable?
What is the error message (if any)?
No explicit error message.
Chrome shows “Page Unresponsive” when opening large workflows.
Docker restarts pods due to healthcheck failures.
No helpful logs – mostly silent hangs.
Please share your workflow
(Complex workflows with 250+ nodes. Can provide sample workflows if needed.)
We also encountered a similar issue with a much simpler workflow containing only around 80 nodes, consisting mostly of dummy IF and SET nodes.
The main problem is that you have so many nodes on the canvas. As all the data keep in the memory while the workflow is executing, it’s better to split a workflow into smaller ones (use sub-workflows) to reduce the complexity and data usage. Plus, AFAIK, the n8n uses only one CPU core, so increasing the number of nodes inside one workflow sooner or later will hang your browser tab and it will be not possible to operate there.
The main “rule” is: Keep a workflow small and simple.
I totally understand the idea of keeping workflows small and simple — but I’d like to get a better sense of what “small” actually means in this context.
A few questions:
What’s the recommended node count limit per workflow?
Is there a rough threshold (e.g., 50 nodes? 100 nodes?) where performance degradation starts to show up?
Or is it more about the types of nodes and how they interact?
Are there any guidelines or best practices on when to split a workflow?
For example, should we avoid more than X number of branching paths or nesting levels?
Even with 50 simple IF nodes (with no real logic inside, just empty placeholders), I saw the exact same issue — the workflow editor became unresponsive and the container restarted due to health check failure.
This seems to happen regardless of whether the nodes are “doing” anything.
Does this mean even the raw node count affects memory/CPU load heavily?
There are no recommendations for that as it’s impossible to calculate. It depends on the node types, instance size, available resource, etc. However, there are recommendations to decrease the memory consumption: Memory-related errors | n8n Docs
Yes, it’s more about that. Some nodes are small and light (Edit Fields, IF, Switch, etc), some others are heavy (like the Code node). Plus it depends or how many data the nodes are processing. You can overload even the Edit Fields node with dozens of variables
It’s more about the designing. But usually you can utilize a sub-workflow in the heavy parts of your workflow:
when you have a Loop node – all nodes behind it could be offloaded into the sub workflow and the loop node may be totally removed (you can execute a sub-workflow for all input items or for each item (like the Loop node does).
when you have repetitive parts with slightly different sections (mostly for IF/Switch parts)
when you have many items to process/transform – better to do the transforming and other manipulations in the sub-workflow, so it will return only the ‘ready-to-use’ data and leaves all data in-between under the hood
That one mostly depends on the size of the input data. But why do you have so many IF nodes? Maybe it should be reconsidered as there is a lot of repetitive parts? You can share a screenshot of the workflow (because, probably, you won’t be able to share the whole workflow due to the characters limit) and I may check which parts most probably could be optimized.
n8n has to render all nodes and links between them on the canvas regardless of that.
It may affect it, but when there is no execution, it mostly affect the user browser. When you hit the Test Workflow button, it affect two parts: browser and the n8n itself (as it should execute nodes, calculate items, render all the steps in the chain, output each step and so on). However, it should be easier for n8n to process your workflow with these settings:
I wanted to share one specific use case we’re struggling with right now.
We’ve created a workflow (screenshot attached) that only contains a series of IF and SET nodes. These nodes basically decide on a response based on the input coming from a Webhook. It’s just a small part of a larger workflow we’re building.
We know this structure is not the most efficient, but we intentionally avoided using the Code node because our non-technical teammates are maintaining these workflows and it’s much easier for them to follow the logic using visual blocks like IF and SET.
Previously on version 0.198, we were using FunctionItem nodes and everything ran smoothly. After upgrading, I tried replacing those with Code nodes — but then encountered execution issues (errors during runs). Based on the memory-related documentation, I switched to using Set nodes instead to reduce pressure — but the issue remains.
Here’s what’s puzzling us:
Even with just this small sub-workflow, when we run the execution, the pod restarts.
I gave the pod generous CPU and memory resources, and monitoring shows it doesn’t hit the resource limits.
But the n8n process seems to become unresponsive, fails the health check, and Kubernetes restarts the container.
So the issue is on both frontend and backend side.
Questions:
Is this kind of visual-heavy workflow structure considered “bad practice” for n8n now?
Is the only viable solution to convert these blocks into Code nodes?
Is there any other approach that keeps workflows visually accessible but avoids this unresponsiveness?
We’re just trying to find a scalable, maintainable way to work with complex flows — especially in teams where not everyone is technical.
Thanks again for your help and any suggestions you can share!
Can you share the first 5-10 nodes alongside with the sample input (you can remove any sensitive content from it)?
You can select all nodes you need and copy them with ctrl+c. Then past the content here after pressing button </> with ctrl+v. I may show additional context about the possible issue
Still, it doesn’t seem to be too big for the n8n to process. However, it may depend on the input data and the set mode (return all input + new variables vs return only some fields).
I also see some patterns on the canvas, which may be easier to offload into a separate sub-workflow. In that case your non-tech guys may implement additional IF logic later and attach it as only one node to the main “chain”
Sure! I’ve prepared a dummy workflow and I’m sharing the first part of it below as requested.
This specific example is just a starting point to reproduce the issue and explore possible improvements.
But I’d like to clarify that this workflow is not the only case where we face problems.
We actually have much more complex workflows — about 5 times bigger, involving not just IF and SET nodes, but also Code nodes and external API integrations. We’ll definitely need a solution for those as well.
Still, if there’s something wrong or inefficient in this smaller workflow, identifying it might help us spot what we’re missing — and maybe improve our entire approach.
Thanks again for taking the time to look into this!
You are turning on the option to include all data for all nodes, however, you don’t need the whole input for them, the nodes can look only for one part of the input data within the first node
you are adding the tag via Array.concat() method, which copies the existing array (5 nodes – 5 more arrays)
Both issues may lead to the significant performance issues with increasing the number of nodes (it behaves as a snowball, which gets bigger each time you add a node)
One solution: migrate to Switch nodes instead of the chain of IFs
Pros:
It won’t duplicate the input data and won’t add any new arrays during the run Cons:
it still ‘heavy’ and hard to expand