Sistava

n8n Memory Issues on Self-Hosted: Causes and Fixes

How-to — — by Mahmoud Zalt

Why n8n executions stop with an out of memory error, what really consumes memory, and how to fix it by processing less rather than buying more RAM.

The workflow worked on 50 rows. It worked on 500. Somewhere between there and the real dataset it stopped finishing, and now a node in the middle reports that the execution stopped and n8n may have run out of memory.

This is the most common wall people hit on a self-hosted instance, and it arrives without warning because nothing was wrong with the design. The workflow is fine. It is simply holding the entire dataset in memory at once, and one day the dataset got bigger than the box.

The useful news is that memory problems in n8n are well documented and the causes are a short list. Once you know which of them applies to your workflow, the fix is usually a change in shape rather than a change in hardware.

What do the memory errors actually mean?

They all mean the same underlying thing: the execution asked for more memory than was available. n8n documents several messages that indicate it, and they differ mostly by where the failure surfaced rather than by cause.

If you see the last of those on a self-hosted instance, you have confirmation rather than a theory. The others are strong signals, and the community reports that memory messages sometimes appear on instances that do not look short of memory, so treat them as a starting point for measurement rather than a verdict.

What actually uses the memory?

n8n lists the factors directly: the amount of JSON data being processed, the size of any binary data, the number of nodes in the workflow, memory-intensive nodes such as the Code node, manual executions, and how many workflows are running at the same time.

The one people never guess is manual executions. n8n documents that a manual run creates copies of the data for the frontend, which is why the same workflow can survive on a schedule and die the moment you press Execute to watch it. If your crash only happens when you are looking at it, that is the reason.

  1. Reproduce it without the editor — Run the workflow on its trigger rather than manually. If it completes, the frontend copies were a large part of your problem.
  2. Find the node that holds the most items — The message names where it stopped, but the cause is usually the node that fetched everything at once, several steps earlier.
  3. Cut the batch size hard — n8n's guidance is to process in smaller chunks, using an example of 200 rows instead of 10,000. Prove the shape works before you tune the number.
  4. Move binary data out of memory — Set the binary data mode so large files are not held in the process. Files are heavier than rows and people forget them entirely.
  5. Split the heavy part into a sub-workflow — Loop Over Items plus Execute Workflow means only the current batch is in memory, and the memory is freed after each one.
  6. Only then consider more memory — If the workload is genuinely large and already chunked, raise the limit deliberately rather than as a first response.

How do you make a workflow hold less at once?

By splitting the work and letting each piece finish. n8n recommends processing data in smaller chunks, giving the example of 200 rows rather than 10,000, and avoiding the Code node where you can because it is memory-intensive by nature.

The stronger pattern is to split the workflow itself. Use the Loop Over Items node to break the data into batches and the Execute Workflow node to hand each batch to a sub-workflow. n8n's documentation is specific about why this helps: the sub-workflow only holds the data for the current batch, and that memory is freed when the batch is done.

That covers the data flowing through your nodes. The other half of memory pressure is files, and files behave differently enough that they need their own setting. A workflow that moves a few hundred documents can be perfectly well behaved on rows and still take an instance down.

Where should binary data live?

Not in the process, if you can help it. n8n exposes N8N_DEFAULT_BINARY_DATA_MODE to control this, with filesystem writing files to disk instead of holding them in memory, and database storing them in your database. n8n's 2.0 breaking changes removed the in-memory mode entirely, leaving filesystem, database or S3.

One constraint matters if you are scaling out. In queue mode you must use the database mode, because the filesystem mode is not supported there. Workers do not share your main instance's disk, so a file written to local disk is not visible to whichever worker picks up the next step.

For genuinely large volumes, n8n documents external storage as an option so binary data lives in object storage rather than on the instance. That is more moving parts to configure and maintain, which is the recurring theme of running your own automation server: every problem you solve adds a component you now own.

It is worth stopping to ask whether you want that job. Chunking, storage modes, heap limits and worker counts are real engineering, and they are engineering about the machine rather than about your business. The employees at Sistava run on infrastructure we size and watch, so the batch size question never reaches you at all.

If you are staying self-hosted, the remaining levers are about giving n8n more room and stopping it from doing too many things at once. Both are legitimate, and both work better after you have fixed the shape of the workflow rather than instead of it.

When is more memory the right answer?

When the workload is genuinely large and already chunked. n8n documents raising the limit through NODE_OPTIONS with the max-old-space-size option, measured in megabytes, which controls how much memory the underlying JavaScript engine will use before it gives up.

Set it below the memory the machine actually has, with headroom for everything else running there. On n8n Cloud the equivalent lever is your plan tier, and self-hosted the equivalent is provisioning a larger server. Neither removes the ceiling, and a workflow with no bound on its dataset will find the new one eventually.

Does concurrency make this worse?

Yes, because concurrent executions share the same memory. n8n lists concurrent workflow executions among the factors, and offers N8N_CONCURRENCY_PRODUCTION_LIMIT to cap them. When the limit is reached, executions wait in a queue and are processed in the order they arrived rather than being dropped.

Beyond that you move to queue mode, setting EXECUTIONS_MODE to queue on the main instance and on every worker, with Redis in between. Each worker takes a concurrency flag that defaults to 10, and n8n notes the main instance's encryption key must be shared with all workers and webhook processors or they cannot use your credentials.

Do not forget the disk

Memory is the loud problem and execution history is the quiet one. n8n prunes finished executions on a schedule by default, using a maximum age of 336 hours, which is 14 days, and a maximum count of 10,000 before it starts deleting oldest first.

Two protections are worth knowing. Executions with a new, running or waiting status are not eligible for pruning, and annotated executions are never pruned, so you can keep an important one deliberately. There is also a hard delete buffer, documented as one hour by default, between soft deletion and the data actually going.

What none of this fixes

It does not fix a workflow with no upper bound on its input. If a node fetches everything a source has and the source keeps growing, every fix here buys time rather than safety. Put a limit on the fetch, not just on the batch.

It also will not resolve the cases people report where memory errors appear on instances that do not look memory constrained. Those are community reports rather than documented behaviour, and they need measurement, which n8n covers in its own guidance on measuring performance, and then a support conversation with your version and figures in hand.

And it does not change the arithmetic. A bigger instance, object storage, Redis and a pool of workers all cost money and attention every month, on top of the hours spent tuning them. Set that against the plans at Sistava before you scale up out of habit, because the cheapest server is often the more expensive option once your time is in the sum.

Whichever way you go, measure before you change anything else. Note how many items the workflow handles, how large the files are and how much memory the instance has, and keep the numbers somewhere. Every decision after this one is easier when you know which of the three actually moved.

FAQ

What does execution stopped at this node mean in n8n?

It is one of the messages n8n documents for memory problems, and it says that n8n may have run out of memory while executing that node. It means the execution needed more memory than the instance had available. The node named is where the process gave up, but the real cause is usually a node earlier in the flow that fetched everything at once and is still holding it.

Why does my n8n workflow crash only when I run it manually?

Because manual executions use more memory. n8n documents that manual runs create copies of the data for the frontend so you can see it in the editor, which adds to what the execution already holds. The same workflow running on its trigger does not pay that cost. If a workflow completes on schedule but dies when you press Execute, that difference is the explanation.

How do I reduce memory use in an n8n workflow?

Process less at once. n8n recommends smaller chunks, using an example of 200 rows rather than 10,000, avoiding the Code node where practical, and avoiding manual executions for large datasets. The strongest pattern is splitting the workflow with the Loop Over Items node and the Execute Workflow node, because the sub-workflow only holds the current batch in memory and that memory is freed when the batch finishes.

How do I give n8n more memory on a self-hosted server?

n8n documents using NODE_OPTIONS with the max-old-space-size option, measured in megabytes, to raise how much memory the underlying JavaScript engine will use. Set it below the memory the machine actually has so there is headroom for everything else running there. On n8n Cloud the equivalent is upgrading your plan. Neither removes the ceiling, so do this after reducing consumption rather than instead of it.

Where should n8n store binary data?

Out of the process. The N8N_DEFAULT_BINARY_DATA_MODE variable controls it, with filesystem writing files to disk and database storing them in your database. n8n 2.0 removed the in-memory mode, leaving filesystem, database or S3. In queue mode you must use the database mode, because the filesystem mode is not supported there and workers do not share your main instance's local disk.

How long does n8n keep execution history?

By default n8n prunes finished executions on a schedule, using a maximum age of 336 hours, which is 14 days, and a maximum count of 10,000 executions before it deletes from oldest to newest. Executions with a new, running or waiting status are not eligible for pruning, and annotated executions are never pruned. There is also a hard delete buffer, documented as one hour by default, between soft deletion and permanent removal.

Sources