How we test VPS servers: we rent each server ourselves, run one script on a fresh Ubuntu install, and publish what it measured, including errors. The script, bench.sh, covers CPU, memory, disk, network, CPU steal, Docker, Supabase and Ollama. A second script, n8n_load.sh, load-tests a real n8n workflow. A full bench.sh run took about 10 minutes on the Hetzner CX43 and about 15 on the CX23.
This page lists every setting, so you can judge our numbers and repeat them. It belongs to our VPS benchmarks; the rules for writing about results are in the editorial policy.
Tested in the Lab Hetzner CX23, CX33, CX43, CAX11, CAX21 · Nov 2026
What bench.sh measures
It runs as root on a new server. First it enables ufw with only SSH open, then records the OS, kernel, CPU model, vCPU count (virtual CPU cores the provider assigns) and RAM used before anything is installed.
| Test | Tool and exact setting | What we record |
|---|---|---|
| CPU, one thread | sysbench cpu --threads=1 --time=20 | events per second |
| CPU, all threads | sysbench cpu --threads=$(nproc) --time=20 | events per second |
| CPU steal | vmstat 1 31, average of 30 one-second samples | % of time the hypervisor gave our vCPU to someone else |
| Memory | sysbench memory --memory-total-size=10G --threads=1 | MiB/s |
| Disk, random | fio 4k blocks, iodepth 32, random read and random write | IOPS (input/output operations per second), MB/s |
| Disk, sequential | fio 1M blocks, iodepth 8, read and write | MB/s |
| Download | curl, 40 s cap: Hetzner hel1 and fsn1 1GB files, CacheFly 100 MB | Mbit/s |
| Latency | ping -c 10 to 1.1.1.1 and 8.8.8.8 | average ms |
| Docker | apt-get install docker.io docker-compose-v2 | install seconds, RAM after |
| Supabase | official docker compose from GitHub, defaults | pull and start time, containers, RAM after 90 s idle, image size |
| Ollama | native install, CPU only, Llama 3.2 1B, 3.2 3B, 3.1 8B | generation and prompt tokens/s, load time, RAM, or the error |
All four fio runs use a 2G test file, --direct=1 (bypassing the page cache, so we measure the disk, not RAM), the libaio engine and 30 s time-based runs.
Ollama details. Every model gets the same prompt about what a VPS is, with num_predict 256 (a 256-token answer), temperature 0 and seed 42, so runs are as repeatable as possible. We send the request twice. Run 1 gives load time and RAM with the model loaded. Run 2, with the model warm, gives tokens/s, computed from Ollama's own eval_count and eval_duration. A token is the unit a model reads and writes, usually a word or part of a word. Each request may take up to 900 s; the model is then unloaded with keep_alive 0. If a model does not run, we publish the error instead of a number.
Here is what the system tests produced on our five Hetzner servers:
| Server | CPU 1 thread events/s | CPU all threads events/s | Memory MiB/s | Disk 4k read IOPS | Disk 4k write IOPS | Disk seq. read | Download | CPU steal | Price / mo |
|---|---|---|---|---|---|---|---|---|---|
| Hetzner CX232 vCPU · 4 GB · x86_64 | 914 | 1,823 | 4,098 | 53,050 | 47,996 | 2,965 MB/s | 285 Mbit/s | 0.0 % | 6.64 €incl. VAT |
| Hetzner CX334 vCPU · 8 GB · x86_64 | 1,621 | 6,453 | 4,974 | 41,644 | 35,013 | 1,936 MB/s | 781 Mbit/s | 0.0 % | 10.27 €incl. VAT |
| Hetzner CX438 vCPU · 15 GB · x86_64 | 3,470 | 26,697 | 4,968 | 45,005 | 42,104 | 2,338 MB/s | 835 Mbit/s | 0.0 % | 19.35 €incl. VAT |
| Hetzner CAX112 vCPU · 4 GB · aarch64 | 3,248 | 6,550 | 4,171 | 48,554 | 42,051 | 2,370 MB/s | 567 Mbit/s | 0.0 % | 7.25 €incl. VAT |
| Hetzner CAX214 vCPU · 8 GB · aarch64 | 3,307 | 13,210 | 4,264 | 53,796 | 46,019 | 2,490 MB/s | 381 Mbit/s | 0.0 % | 12.69 €incl. VAT |
Measured by AI Hosting Lab on 2026-11-05 · 5 servers · method · raw data
What n8n_load.sh measures
It installs n8n 2.46.6 with Postgres 16 using the same images as our production server, creates an owner account and API key through n8n's REST API, and activates one workflow: Webhook → Code node (running in a task runner) → response. After a warm-up of 200 requests at 5 concurrent, ApacheBench (ab) sends POST requests at 1, 10, 25 and 50 concurrent connections: 300 requests at concurrency 1, and 40 per connection above that. We record executions per second, median and 95th-percentile latency (95% of requests were faster), failed and non-2xx responses, and n8n's peak RAM sampled with docker stats.
The test talks to 127.0.0.1 without TLS, so it measures n8n and Postgres, not your network or the proxy. Results are published once all runs are complete:
| Server | Concurrent requests | Executions/s | Median | p95 | Failed | n8n peak RAM |
|---|---|---|---|---|---|---|
| Hetzner CX232 vCPU · 4 GB · x86_64 | 1 | 10.1 | 104 ms | 162 ms | 0 | 520 MiB |
| Hetzner CX232 vCPU · 4 GB · x86_64 | 10 | 14.8 | 697 ms | 893 ms | 0 | 660 MiB |
| Hetzner CX232 vCPU · 4 GB · x86_64 | 25 | 15.0 | 1,651 ms | 1,936 ms | 0 | 825 MiB |
| Hetzner CX232 vCPU · 4 GB · x86_64 | 50 | 14.2 | 3,445 ms | 3,954 ms | 0 | 1,003 MiB |
| Hetzner CX334 vCPU · 8 GB · x86_64 | 1 | 13.5 | 72 ms | 133 ms | 0 | 543 MiB |
| Hetzner CX334 vCPU · 8 GB · x86_64 | 10 | 31.9 | 311 ms | 438 ms | 0 | 574 MiB |
| Hetzner CX334 vCPU · 8 GB · x86_64 | 25 | 29.5 | 841 ms | 986 ms | 0 | 803 MiB |
| Hetzner CX334 vCPU · 8 GB · x86_64 | 50 | 30.1 | 1,647 ms | 1,846 ms | 0 | 1,050 MiB |
| Hetzner CX438 vCPU · 15 GB · x86_64 | 1 | 14.6 | 78 ms | 123 ms | 0 | 546 MiB |
| Hetzner CX438 vCPU · 15 GB · x86_64 | 10 | 36.1 | 280 ms | 341 ms | 0 | 544 MiB |
| Hetzner CX438 vCPU · 15 GB · x86_64 | 25 | 35.0 | 714 ms | 800 ms | 0 | 694 MiB |
| Hetzner CX438 vCPU · 15 GB · x86_64 | 50 | 32.4 | 1,539 ms | 1,682 ms | 0 | 1,016 MiB |
| Hetzner CAX112 vCPU · 4 GB · aarch64 | 1 | 10.3 | 113 ms | 156 ms | 0 | 585 MiB |
| Hetzner CAX112 vCPU · 4 GB · aarch64 | 10 | 13.9 | 755 ms | 934 ms | 0 | 640 MiB |
| Hetzner CAX112 vCPU · 4 GB · aarch64 | 25 | 12.9 | 1,909 ms | 2,279 ms | 0 | 729 MiB |
| Hetzner CAX112 vCPU · 4 GB · aarch64 | 50 | 13.2 | 3,786 ms | 4,114 ms | 0 | 1,038 MiB |
| Hetzner CAX214 vCPU · 8 GB · aarch64 | 1 | 12.0 | 107 ms | 128 ms | 0 | 539 MiB |
| Hetzner CAX214 vCPU · 8 GB · aarch64 | 10 | 25.4 | 402 ms | 528 ms | 0 | 579 MiB |
| Hetzner CAX214 vCPU · 8 GB · aarch64 | 25 | 25.8 | 965 ms | 1,106 ms | 0 | 824 MiB |
| Hetzner CAX214 vCPU · 8 GB · aarch64 | 50 | 24.5 | 2,019 ms | 2,197 ms | 0 | 859 MiB |
Measured by AI Hosting Lab on 2026-11-05 · 5 servers · method · raw data
What we pay for
We rent every server on our own Hetzner account at the normal hourly rate, for example 0.0106 € per hour gross for a CX23, from the Hetzner Cloud API price list checked on 2026-11-05. Our production n8n server is a CX23 at 6.64 € per month. We never buy through our own affiliate links, and no provider pays for or reviews a test. See the affiliate disclosure for how links are handled.
Limits you should know
- One run per server. We have not repeated runs across days yet, so a number is one sample, not an average.
- Shared vCPUs vary. All five servers are shared-CPU plans. Steal was 0.0% during our 30 s window on all of them, but a neighbour can change that an hour later.
- One provider, one location. Hetzner, Helsinki (hel1) only, so far. Other providers are marked "not yet tested" until we run them.
- Two Ubuntu versions. Test servers ran Ubuntu 24.04; our production n8n server runs 26.04. We label which is which.
- CPU only, idle Supabase. No GPU tests yet, and Supabase is measured idle, not under load.
How results are published
Each run writes key=value lines and raw tool output (sysbench text, fio JSON, Ollama JSON). We store one JSON file per server and test under lab/results/, named by date, provider, plan and location, and combine them into one lab.json. Every table and chart on this site is rendered from that file at build time, so a number in an article cannot drift from the measurement. When we rerun a server, the page shows the new date.
Next step: see the results side by side in our VPS benchmarks.
Hetzner prices on this page include 21% VAT, as charged to our Czech (EU consumer) account by the Hetzner API on 2026-11-05. Without VAT (businesses, most buyers outside the EU): CX23 5.49 €, CX33 8.49 €, CX43 15.99 €, CAX11 5.99 €, CAX21 10.49 € per month.
FAQ
Do you buy the servers you test?
Yes. We rent every server on our own account at the normal hourly price and never through our own affiliate links.
How many times do you run each benchmark?
Once per server so far. The Ollama test sends the same prompt twice and reports the second, warm run. We say so wherever a number is shown.
Which providers have you tested?
Hetzner Cloud only so far: CX23, CX33, CX43, CAX11 and CAX21 in Helsinki, plus our production CX23. Other providers are scheduled and are marked as not yet tested.
Can I run your benchmark myself?
Yes. bench.sh runs as root on a fresh Ubuntu server and writes key=value lines plus raw JSON files, so you can compare your server with ours.

