n8n's VPS requirements are modest on CPU, and memory is what runs out first. In our load test of n8n 2.42.6 in Docker, an idle n8n with PostgreSQL used about 510 MB of RAM in total. One shared vCPU handled about 10 simple webhook executions per second, two vCPUs about 18, and four vCPUs about 27. For most people the right n8n VPS is 2 vCPU and 2 GB of RAM. 1 GB works for light personal use, but only with a concurrency limit, because our 1 GB server crashed when 50 requests arrived at once. Heavy workflows that pass thousands of items between nodes are where 4 GB starts to matter.
Key facts, checked on 9 October 2026:
- n8n's prerequisites page for embedded deployments says n8n "isn't CPU intensive" and lists 320 MB to 2 GB of memory (n8n docs). We measured 381 to 413 MiB for the n8n container alone at idle.
- n8n's benchmark page reports up to 220 workflow executions per second on a single instance, tested on an AWS c5a.large with 4 GB of RAM (n8n performance benchmarking). The page does not say which n8n version was used.
- Since n8n 2.35.0, expressions run in a sandboxed V8 isolate by default (
N8N_EXPRESSION_ENGINE=vm, n8n docs). In our profile this sandbox was the largest single CPU cost of a simple workflow. - Concurrency control is "disabled by default". Once you set a limit, extra production executions wait in a queue and run in FIFO order (n8n concurrency control).
- Queue mode needs Redis and a real database. Each worker runs 10 jobs at once by default, and SQLite isn't supported for this setup (n8n queue mode).
n8n VPS requirements: the sizing table first
Measured ceilings from our lab, and the load we would plan for: about a third of the ceiling, which leaves room for the editor, scheduled jobs and bursts. A "simple workflow" is Webhook, Edit Fields and Respond to Webhook. "Heavier" means a Code node or an HTTP Request node that pulls in 200 items, plus a Code node returning 2,000 items on the 4 vCPU size.
| Plan | Simple workflow, measured ceiling | Heavier workflows, measured ceiling | Plan for | Good fit |
|---|---|---|---|---|
| VPS Nano (1 vCPU, 1 GB) | 10 per second | 9 per second (Code, HTTP), with 20 at a time at most | About 200 per minute, with N8N_CONCURRENCY_PRODUCTION_LIMIT set | Personal automations, a few webhooks, learning n8n |
| VPS Micro (2 vCPU, 2 GB) | 18 to 19 per second | 17 per second (Code, HTTP) | About 350 per minute, or roughly 500,000 a day | A small business: shop and form webhooks, CRM sync, Telegram bots |
| VPS Mini (4 vCPU, 4 GB) | 26 to 29 per second | 10 per second with 2,000 items, 14 with two queue workers | About 500 per minute simple, or 200 per minute heavy | Several users, AI agents, big JSON or file processing, queue mode |
| VDS Small (4 vCPU, 8 GB) | Not tested | Not tested | Same 4 vCPUs as Mini, so expect similar throughput with twice the memory | Large files, many workers, Postgres plus other apps on one server |
For scale: a workflow that runs once a minute all day is 1,440 executions. Most n8n servers never get near these ceilings. They run out of memory during a burst long before they run out of CPU.
How we tested, and what that means for the numbers
All numbers come from our lab on 9 October 2026, on an Amsterdam test server with an AMD EPYC 7742 (8 cores, 15 GB of RAM). n8n ran in a Debian 13 container limited to each plan's size: 1 vCPU and 1 GB, then 2 and 2, then 4 and 4, with swap off. A second container sent the traffic with hey, a small HTTP load tool from Debian's archive.
- Software: n8n 2.42.6 (the official image, 1.06 GB), PostgreSQL 17, Redis 7 and Docker 26.1.5.
- Each step lasted 20 seconds at 1, 5, 20, 50 and 100 concurrent requests, meaning that many requests waiting for an answer at once.
- We report requests per second and p95 latency. A p95 of 0.27 seconds means 95 out of 100 requests got their answer within 0.27 seconds.
- Every execution was saved to the database, as n8n does by default.
The limits, plainly: vCPUs on a VPS are shared, and other test labs ran on the same host during our runs. Treat the results as a guide, expect a few percent of variation, and remember that on a real VPS the operating system and other software need their share too.
Result 1: idle memory
We measured memory after two minutes without traffic, with docker stats --no-stream for each container and free -m for the whole server.
| Setup | n8n container | Database and Redis | Whole server in use |
|---|---|---|---|
| 1 vCPU, 1 GB, SQLite | 394 MiB | inside n8n | 484 MB |
| 1 vCPU, 1 GB, PostgreSQL | 381 MiB | 46 MiB | 512 MB |
| 2 vCPU, 2 GB, PostgreSQL | 413 MiB | 44 MiB | 510 MB |
| 4 vCPU, 4 GB, PostgreSQL | 388 MiB | 39 MiB | 535 MB |
| 4 vCPU, 4 GB, queue mode, 1 worker | 301 MiB main + 299 MiB worker | 36 MiB + 18 MiB | 760 MB |
A fresh n8n takes about half a gigabyte before it does any work. That is well above the figure of about 100 MB that n8n's prerequisites page gives for an idle n8n Cloud instance. Besides the main process, the Docker image starts a task runner for Code nodes and a sandbox for expressions. After a restart on 1 vCPU with SQLite, the first webhook answered after 14 seconds.
Result 2: a simple webhook workflow under load
The workflow most people start with: a webhook receives JSON, Edit Fields adds two values with expressions, and Respond to Webhook answers. Postgres, except where noted.
| Requests at the same time | Nano: 1 vCPU, 1 GB | Micro: 2 vCPU, 2 GB | Mini: 4 vCPU, 4 GB |
|---|---|---|---|
| 1 | 9.5/s, p95 0.20 s | 14.3/s, p95 0.13 s | 16.9/s, p95 0.10 s |
| 5 | 9.9/s, p95 0.66 s | 18.4/s, p95 0.38 s | 26.1/s, p95 0.27 s |
| 20 | 9.9/s, p95 2.52 s | 18.9/s, p95 1.24 s | 27.5/s, p95 0.85 s |
| 50 | Crashed: out of memory (SQLite run) | 18.7/s, p95 3.07 s | 25.4/s, p95 2.22 s |
| 100 | Not run | 18.7/s, p95 5.69 s | 26.4/s, p95 4.23 s |
| Peak RAM in use | 702 MB at 20 | 1,345 MB at 100 | 1,256 MB at 100 |
Throughput flattens early: past 5 to 20 concurrent requests, more traffic only means longer waits. Going from 1 to 2 vCPUs almost doubled throughput; going from 2 to 4 added about 45%. Memory grows with the number of executions in flight. Micro and Mini returned no errors at any level, only slower answers.
Why so far below n8n's 220 per second? Node.js's built-in CPU profiler showed that the largest single cost was @n8n/expression-runtime, the expression sandbox. More on that below.
Result 3: what 50 requests at once do to 1 GB
At 50 concurrent requests the 1 GB server ran out of memory. The kernel's OOM killer (the part of Linux that ends a process when memory runs out) struck 7 times during our 50-request tests, and Docker restarted n8n 4 times. While n8n started up again, webhooks answered 404 The requested webhook "POST light" is not registered, and the log said Last session crashed. A shop sending order webhooks would have lost orders.
The fix is one line. With concurrency control, n8n runs a set number of production executions at a time and queues the rest. Add it to the n8n service's environment: list:
# in docker-compose.yml, under the n8n service's environment:
- N8N_CONCURRENCY_PRODUCTION_LIMIT=5
Then apply it:
# as the n8n user, in ~/n8n
docker compose up -d
On the rerun, all 244 requests got a 200 answer, at 10.2 per second with a p95 of 5.3 seconds, and memory stayed at 608 MB. Slower, but no crash. To see whether your own n8n has been crashing, check the restart count; anything above 0 that you didn't cause needs a look:
# as the n8n user, in ~/n8n
docker inspect n8n-n8n-1 --format '{{.RestartCount}}'
docker compose logs n8n | grep -c "Last session crashed"
docker compose ps shows your container name. One more trap on 1 GB: n8n's command line tools, such as n8n import:workflow, start a second full n8n. Next to a running n8n they caused three more OOM kills in our lab, so stop n8n first.
Result 4: the node type changes the numbers
A Code node that builds and sums 5,000 records was barely slower than the simple workflow, and so was an HTTP Request node fetching 200 products from a local web server. What hurts is the number of items flowing between nodes. A Code node returning 2,000 small order records cut throughput by more than half and nearly doubled the server's memory use.
| Workflow | Size | At 20 concurrent | n8n memory at 100 concurrent | Stored per execution |
|---|---|---|---|---|
| Webhook, Edit Fields, Respond | Micro | 18.9/s, p95 1.24 s | 1.12 GiB | 1.1 KB |
| Code node, 5,000 records summed | Micro | 16.9/s, p95 1.50 s | 1.63 GiB | 1.1 KB |
| HTTP Request, 200 items back | Micro | 17.2/s, p95 1.41 s | 1.50 GiB | 10.6 KB |
| Code node returning 2,000 items | Mini | 10.2/s, p95 2.32 s | 2.13 GiB (2,338 MB for the whole server) | 83.6 KB |
"Stored" is the average size of one saved execution in PostgreSQL. n8n's memory error guide names the same causes: the amount of JSON and binary data, the number of nodes, and the Code node. So split big jobs into batches, pass on only the fields the next node needs, and use sub-workflows that return a short result. At 100 concurrent requests, the 2,000-item workflow used 2,338 MB, more than a 2 GB server has.
SQLite or PostgreSQL?
SQLite, n8n's default, is a single database file in n8n's data folder. PostgreSQL is a database server running next to n8n. For speed, we found almost no difference:
| Test | SQLite | PostgreSQL 17 |
|---|---|---|
| Nano, simple workflow, 20 concurrent | 10.4/s, p95 2.21 s | 9.9/s, p95 2.52 s |
| Mini, simple workflow, 100 concurrent | 27.4/s, p95 3.76 s | 26.4/s, p95 4.23 s |
| Mini, 2,000 items, 20 concurrent | 10.6/s, p95 2.14 s | 10.2/s, p95 2.32 s |
The bottleneck is n8n itself, not the database. We still recommend PostgreSQL for anything you rely on: queue mode won't run on SQLite, Postgres costs only about 40 MB of RAM at idle, and SQLite files don't shrink. Ours grew to 616 MB, because pruned data is reused but not released unless you vacuum the database (n8n execution data docs). By default n8n deletes saved executions after 14 days or beyond 10,000. Our database server guide covers Postgres in more depth.
Queue mode on 4 vCPUs: when it pays
In queue mode, the main n8n process only receives webhooks and triggers and puts each job into Redis, a fast in-memory store. Separate worker processes run the jobs.
| Setup on Mini | Simple, 100 concurrent | 2,000 items, 20 concurrent | 2,000 items, 100 concurrent | RAM in use, 2,000 items at 100 |
|---|---|---|---|---|
| Regular mode | 26.4/s, p95 4.23 s | 10.2/s, p95 2.32 s | 9.5/s, p95 12.09 s | 2,338 MB |
| Queue mode, 1 worker | 28.5/s, p95 3.73 s | 10.5/s, p95 2.25 s | 10.1/s, p95 10.08 s | 1,383 MB |
| Queue mode, 2 workers | 31.2/s, p95 3.86 s | 14.2/s, p95 1.87 s | 14.0/s, p95 7.50 s | 2,694 MB |
One worker didn't make n8n faster, but it made memory predictable: it takes 10 jobs at a time, the rest wait in Redis, and RAM stayed near 1.4 GB instead of passing 2.3 GB. A second worker raised heavy throughput by about 35%. On 4 vCPUs we would stop at two; beyond that, a VDS plan with more cores fits better. The worker is the same image started with worker, sharing the database, Redis and encryption key. These are the lines we added to the Postgres setup shown further down:
# in docker-compose.yml: added to the environment of n8n AND worker
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- N8N_ENCRYPTION_KEY=${ENCRYPTION_KEY}
- OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true
# new services next to postgres and n8n
redis:
image: redis:7-alpine
restart: unless-stopped
worker:
image: docker.n8n.io/n8nio/n8n:2.42.6
command: worker
# same environment and volumes as the n8n service
The encryption key caught us out. n8n creates a random key on first start. Set a different N8N_ENCRYPTION_KEY and both n8n and the worker stop with Mismatching encryption keys and keep restarting. Read the existing key before you switch and put it in .env as ENCRYPTION_KEY=...:
# as the n8n user, in ~/n8n, while n8n is still running
docker compose exec n8n cat /home/node/.n8n/config
It prints {"encryptionKey": "..."}. Your saved credentials are encrypted with it, so keep a copy safe. Then docker compose up -d starts everything, and docker compose up -d --scale worker=2 adds a second worker.
A side note on the expression engine
We also tried n8n's older engine with N8N_EXPRESSION_ENGINE=legacy. The simple workflow went from 18.9 to 62.2 executions per second on 2 vCPUs, and reached 62.5 on 4. The 2,000-item workflow barely moved (10.6 to 11.5), because its cost is data, not expressions. A bigger pool of warm sandboxes (N8N_EXPRESSION_ENGINE_POOL_SIZE 2 or 4) didn't help. We don't recommend the switch: the legacy engine runs expressions without isolation, and n8n plans to deprecate it. More vCPUs or queue workers are the safer answer.
Run the same test on your own server
This is the PostgreSQL setup we tested, minus the mock web server the HTTP test needed. Our n8n install guide covers Docker, the firewall and the first login step by step.
# ~/n8n/docker-compose.yml, owned by the n8n user
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=n8n
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n"]
interval: 5s
retries: 10
n8n:
image: docker.n8n.io/n8nio/n8n:2.42.6
restart: unless-stopped
ports:
- "5678:5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
- GENERIC_TIMEZONE=Europe/Amsterdam
- N8N_DIAGNOSTICS_ENABLED=false
- N8N_SECURE_COOKIE=false
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
volumes:
pg_data:
n8n_data:
N8N_SECURE_COOKIE=false is there only because our lab had no HTTPS. On a real server, use a reverse proxy with a TLS certificate and remove that line. Then create the password file and start:
# as the n8n user, in ~/n8n
printf 'DB_PASSWORD=%s\n' "$(openssl rand -hex 16)" > .env
chmod 600 .env
docker compose up -d
docker compose ps
In the STATUS column of docker compose ps, postgres should read Up with (healthy) at the end, and n8n should read Up. On our 1 vCPU size, n8n answered about 14 seconds after it started. In the editor, build and publish a test workflow: a Webhook node (POST, path light, answering through the Respond to Webhook node), an Edit Fields node and a Respond to Webhook node. Then send traffic from a second machine you control:
# as root on the second machine (Debian 13)
apt install -y hey
echo '{"name":"lab"}' > body.json
hey -z 20s -c 20 -m POST -T application/json -D body.json http://YOUR_SERVER_IP:5678/webhook/light
Use your reverse proxy's HTTPS address if port 5678 isn't reachable, and only test servers you own. Read Requests/sec, the 95% in line and Status code distribution, which should show only [200]. On our 2 vCPU size this gave 18.9 requests per second. Meanwhile, watch memory on the n8n server:
# as the n8n user, on the n8n server
docker stats --no-stream
free -m
Start at -c 1 and raise it step by step. When requests per second stop rising, you have found your ceiling. For CPU, disk and network tests, see our VPS benchmark commands; for ongoing alerts, Uptime Kuma or Grafana.
Disk space: plan for the image and the history
- The n8n image is 1.06 GB, and Postgres 17 Alpine adds 297 MB. Updates download new layers, so keep 3 to 4 GB free for images.
- Saved executions add up: 1 KB each for a simple workflow, 84 KB for one that moves 2,000 items. 10,000 heavy executions take about 840 MB.
EXECUTIONS_DATA_SAVE_ON_SUCCESS=nonestops saving successful runs. It saves disk, but it didn't make n8n faster on 1 vCPU (10.4 per second either way).
Frequently asked questions
What are the minimum VPS requirements for n8n?
In our test, n8n 2.42.6 ran on 1 shared vCPU and 1 GB of RAM and handled about 10 simple webhook executions per second. It crashed when 50 requests arrived at once. Setting N8N_CONCURRENCY_PRODUCTION_LIMIT=5 fixed that. For production use, 2 vCPU and 2 GB is the safer minimum.
How much RAM does n8n use?
An idle n8n 2.42.6 Docker container used 381 to 413 MiB in our lab, and about 510 MB for the whole server with PostgreSQL. Under load it reached 1.1 to 1.6 GiB at 100 concurrent requests, and 2.1 GiB for a workflow passing 2,000 items between nodes.
Is 1 GB of RAM enough for n8n?
For a few personal workflows, yes, with a concurrency limit and nothing else heavy on the server. Without a limit, n8n on our 1 GB server ran out of memory at 50 concurrent requests and restarted 4 times, and webhooks sent meanwhile got 404 errors or no answer.
How many executions per second can n8n handle?
In our lab, a simple webhook workflow reached about 10 per second on 1 vCPU, 18 on 2 vCPUs and 27 on 4 vCPUs, with n8n's default sandboxed expression engine. n8n's own benchmark reports up to 220 per second on a single AWS instance, without naming the version. Heavy workflows with thousands of items are several times slower.
Should I use SQLite or PostgreSQL for n8n?
Speed was nearly identical in our tests, within about 5%. Use PostgreSQL for anything you rely on: queue mode doesn't support SQLite, Postgres needs only about 40 MB of RAM at idle, and an SQLite file never shrinks on its own after old executions are pruned.
When do I need n8n queue mode?
Use queue mode when memory spikes from many parallel executions, or when one server is no longer enough. On 4 vCPUs, one worker kept RAM at 1.4 GB instead of 2.3 GB under heavy load, and a second worker raised heavy throughput by about 35%. It needs Redis, PostgreSQL and the same encryption key on every process.
Pick a size and start small
For most people, a 2 vCPU, 2 GB server with PostgreSQL and a concurrency limit is all n8n needs. Move to 4 vCPU and 4 GB when your workflows pass thousands of items, or when you want queue workers. RS Computers runs KVM VPS and VDS servers in Amsterdam, Dublin and Prishtina, all with NVMe, unmetered traffic and their own IPv4 and IPv6. You can upgrade to a bigger plan later from the client area with a short reboot. Compare sizes and city availability on the plans page, read about n8n hosting with us, or ask us on Telegram if you want help sizing a server for your workflows.