PostgreSQL on Hetzner vs ServersCamp: a ~EUR 100 database server
You have about a hundred euros a month and a database that intends to grow. What do you actually get for that money? We bought the closest thing to the same database server from Hetzner and from ourselves, put vanilla PostgreSQL 18.4 on both, and ran the same pgbench battery over a ladder of database sizes: from fits-in-RAM to ten times bigger than RAM. Every command is in this article; the whole thing reproduces in an afternoon from a plain console.
TL;DR
Writes, commits, big databases
ServersCamp wins
TPC-B writes: +13% to +18% at every database size Raw commit rate: 41.9k/s vs 34.8k/s (+20%) at lower latency Reads on 44-88 GB databases: +12% Bulk load 1.6x faster, latency lower everywhere, jitter roughly half
Small in-RAM databases, reads
Hetzner wins
2x the RAM for the money: 16 GB vs our 8 Reads on a 1.5 GB database: 48.3k vs 43.5k qps (+10%) Reads at the 15 GB cache edge: +5% And the check is EUR 16.73 smaller
The contenderstop
| Hetzner | ServersCamp | |
|---|---|---|
| DB server | CCX23, "4 dedicated vCPU" / 16 GB | hf-m Sustained, 4 vCPU / 8 GB |
| CPU | AMD EPYC Milan | AMD EPYC 4565P, up to 5.7 GHz |
| Disk | 160 GB local NVMe, included | 160 GB Database-class W4: replicated network NVMe with power-loss protection, 150k IOPS / 2 GB/s |
| What kills the disk | The host dying kills it | Survives the host: replicated across nodes |
| Network between the two VMs | Public IPs in one DC (private networks exist but are extra setup); ping RTT avg 0.81 ms | Default private network, zero setup; ping RTT avg 0.13 ms |
| OS / PostgreSQL | Ubuntu 26.04, PostgreSQL 18.4 from PGDG, same pgtune OLTP formula on both (values from each box's own RAM/cores) | |
| Client VM (not part of the compared check) | CPX22, 2 shared vCPU / 4 GB, EUR 19.99 | hf-s, 2 vCPU / 4 GB, EUR 20.50 |
| Monthly check, incl. IPv4 | EUR 86.49 | EUR 103.22 |
The checks differ by EUR 16.73 and the machines differ in shape: Hetzner spends the money on 2x the RAM, we spend it on faster cores and a disk that survives its host. Neither side gets to normalize that away: each provider sells the stack it sells, and a buyer gets the whole stack or none of it. The size ladder below is designed to show exactly where each choice pays.
Method, in one paragraphtop
Standard pgbench, PostgreSQL 18.4, client on a separate small VM talking over each provider's network, because that is how applications talk to databases. TPC-B (write-heavy: three UPDATEs, an INSERT and a COMMIT per transaction) at 32 connections for 5 minutes per point; select-only reads at 32 connections for 2 minutes; a raw commit-rate test (single INSERT + COMMIT, 64 writers). Database sizes: scale 100 / 1000 / 3000 / 6000, which is 1.5 / 15 / 44 / 88 GB against 16 GB of RAM on one side and 8 GB on the other. One pass per point, no retries, no tuning beyond the same public pgtune formula on both. Full command list at the bottom.
Writestop
| Database size | Hetzner tps (latency) | ServersCamp tps (latency) | Δ tps |
|---|---|---|---|
| 1.5 GB (in RAM both) | 5,680 (5.62 ms) | 6,724 (4.74 ms) | +18% |
| 15 GB (cache edge) | 5,182 (6.16 ms) | 5,840 (5.47 ms) | +13% |
| 44 GB (disk territory) | ~5,000* (~6.3 ms) | 5,631 (5.67 ms) | +13% |
| 88 GB (deep disk) | 4,726 (6.76 ms) | 5,504 (5.80 ms) | +16% |
Three things worth knowing behind these bars:
- Both boxes hit their CPU ceiling, not their disks. During every write run, both servers sat at 97-100% CPU. TPC-B at these sizes is a contention-and-commit test, and no amount of disk speed lifts it. We verified with 128 clients on the 44 GB point: Hetzner got 4,997 tps (nothing gained, latency x4), ServersCamp 5,335 (+7%, latency x4). More connections added queueing on both sides and nothing else.
- The latency gap is the network gap. A TPC-B transaction is seven round trips. On Hetzner's out-of-the-box path (public IPs in one DC) that is 7 x 0.81 ms of wire time inside every transaction; on ServersCamp's default private network it is 7 x 0.13 ms. You can configure a private network at Hetzner too; it just does not come configured.
- Steadiness differs more than the averages. ServersCamp's per-10-second jitter (stddev 1.1-1.7 ms) ran at roughly half of Hetzner's (1.9-2.9 ms), and the Hetzner 88 GB run shows a visible sawtooth (4.3k to 5.0k) where checkpoints bite. Flat lines are what your p95 is made of.
Reads: the cache laddertop
| Database size | Hetzner qps (latency) | ServersCamp qps (latency) | Δ qps |
|---|---|---|---|
| 1.5 GB | 48,261 (0.65 ms) | 43,514 (0.73 ms) | -10% |
| 15 GB | 31,886 (1.00 ms) | 30,206 (1.05 ms) | -5% |
| 44 GB | 26,549 (1.20 ms) | 27,090 (1.18 ms) | +2% |
| 88 GB | 22,544 (1.41 ms) | 25,303 (1.26 ms) | +12% |
| 44 GB, right after an hour of writes | 21,882 (1.46 ms) | 24,837 (1.28 ms) | +13.5% |
Unlike writes, reads scale with database size on both boxes, and the crossover is the story. On a small hot database Hetzner's extra RAM and its read path win: 48k qps is an excellent number. As the database outgrows RAM the order reverses, and by 88 GB the ServersCamp box reads 12% faster despite having half the RAM to cache with: the replicated network disk answers point reads faster than their local NVMe once real disk IO is in the loop.
The last row is the one production people will recognize. We measured the 44 GB read test twice on each box: once on a freshly loaded database and once right after a long write workload had chewed the same tables (bloat, dirty pages, the state your database actually lives in). Hetzner lost 18% to that churn; ServersCamp lost 8% and ended up 13.5% ahead. Benchmarks run on pristine data; Tuesday afternoon does not.
Raw commit rate: the number databases live ontop
| Hetzner | ServersCamp | |
|---|---|---|
| Commits per second, 64 writers | 34,800 | 41,878 (+20%) |
| Latency per commit | 1.82 ms | 1.51 ms |
This test strips the workload to its skeleton: one INSERT, one COMMIT, 64 clients hammering it. Every commit has to reach durable media before PostgreSQL answers, so this is a direct measurement of the WAL-fsync path: the thing every transactional database queues behind. The ServersCamp disk is a replicated network volume with power-loss-protected write cache, and it out-commits Hetzner's local NVMe by 20% while writing every byte twice across independent nodes. This mirrors what our fio storage benchmark measured a week earlier with parallel fsync: it is a hardware property, not a lucky run.
Bulk load, since you will restore a dump one daytop
| pgbench -i (load + index) | Hetzner | ServersCamp |
|---|---|---|
| 15 GB | 78-90 s | 50-57 s |
| 44 GB | 242-244 s | 149-152 s |
| 88 GB | 487 s | 295 s (1.65x faster) |
Loading 88 GB with indexes took 8 minutes on ServersCamp and 8 minutes plus most of a coffee on Hetzner. The same ratio will apply to the restore you run at 3 AM some day, which is when you will care about it most.
Throughput per eurotop
| Metric, divided by the monthly check | Hetzner (EUR 86.49) | ServersCamp (EUR 103.22) |
|---|---|---|
| Write tps per euro, 88 GB database | 54.6 | 53.3 |
| Write tps per euro, 1.5 GB database | 65.7 | 65.1 |
| Commits/s per euro | 402 | 406 |
| Read qps per euro, 88 GB database | 260.7 | 245.1 |
| Read qps per euro, 1.5 GB database | 558.0 | 421.6 |
Divide everything by the money and the picture changes: on writes and commits the two boxes deliver almost identical throughput per euro, and on reads Hetzner's smaller check wins the ratio outright. The extra EUR 17 a month does not buy more transactions per euro. What it buys is the shape of those transactions: 15-17% lower latency, half the jitter, no checkpoint sawtooth, a 1.6x faster restore, and the difference between a disk that dies with its host and one that does not. Whether that is worth EUR 17 is exactly the decision this article exists to inform.
What else is inside the checkstop
The tps tables are half of the purchase. The other half is what happens to this database over a year of operating it, and here the two checks buy structurally different things:
- The disk itself. Hetzner's NVMe is local: if that host dies, the disk and the database die with it, and recovery means restoring backups onto new hardware. The ServersCamp volume is replicated across storage nodes: a dead host restarts the VM elsewhere with the disk intact, mid-transaction durability included.
- Growing. The Hetzner disk is 160 GB, full stop; the next size means the next instance. The ServersCamp volume resizes online and changes speed class in place while the database keeps running.
- Backups that leave the building. Snapshots plus encrypted off-cluster backups to another provider in another country, with your key, are one toggle. On the other side you build this yourself.
- The network you saw in the latency column. The private network that made every transaction 4.7 ms instead of 5.6 exists from the first minute, unconfigured.
- The perimeter. Warden's live traffic map is free on every ServersCamp resource; this database server spent the whole benchmark watchable.
Verdict: who should buy whichtop
| Your situation | Buy | Why |
|---|---|---|
| Small database that fits in RAM, read-heavy, budget-first | Hetzner CCX23 | 48k in-cache qps for EUR 86 is the best line item in this article |
| Write-heavy anything: OLTP, queues, event streams | ServersCamp | +13-18% tps at every size, +20% raw commits, lower latency, half the jitter |
| A database that will outgrow RAM (they all do) | ServersCamp | The deep-ladder points: +12-16% at 88 GB on both reads and writes, and the gap widens with churn |
| Anything you cannot afford to lose with the host | ServersCamp | Every Hetzner number above is conditional on one physical machine staying alive; ours are not |
Reproduce ittop
Two VMs per side, PostgreSQL 18 from PGDG on the server (pgtune-formula config printed below), postgresql-client-18 on the client, then this console session. That is the entire methodology:
export PGHOST=<server-ip> PGUSER=bench PGDATABASE=bench PGPASSWORD=...
ping -c 20 $PGHOST | tail -2
pgbench -i -s 100
pgbench -c 32 -j 2 -T 300 -P 10 # writes, 1.5 GB
pgbench -i -s 1000
pgbench -c 32 -j 2 -T 300 -P 10 # writes, 15 GB
pgbench -i -s 3000
pgbench -c 32 -j 2 -T 300 -P 10 # writes, 44 GB
pgbench -S -c 32 -j 2 -T 120 -P 10 # reads, 44 GB (after the writes)
pgbench -i -s 100
pgbench -S -c 32 -j 2 -T 120 -P 10 # reads, 1.5 GB fresh
pgbench -i -s 1000
pgbench -S -c 32 -j 2 -T 120 -P 10 # reads, 15 GB fresh
pgbench -i -s 3000
pgbench -S -c 32 -j 2 -T 120 -P 10 # reads, 44 GB fresh
pgbench -i -s 6000
pgbench -c 32 -j 2 -T 300 -P 10 # writes, 88 GB
pgbench -S -c 32 -j 2 -T 120 -P 10 # reads, 88 GB
echo "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (1, 1, 1, 1, now());" > ins.sql
pgbench -f ins.sql -c 64 -j 2 -T 120 -P 10 # raw commit rate
Server config, same formula both sides (shown for the 8 GB box; the 16 GB box gets proportionally larger memory values):
max_connections = 200
shared_buffers = 2GB # RAM/4
effective_cache_size = 6GB # RAM x 3/4
maintenance_work_mem = 512MB
work_mem = 10MB
wal_buffers = 16MB
min_wal_size = 2GB
max_wal_size = 16GB
checkpoint_completion_target = 0.9
random_page_cost = 1.1
effective_io_concurrency = 256
If your numbers on a ServersCamp VM come out below what this page claims, that is a bug: tell us in a ticket.
Disclaimerstop
- One pass per point, run on 2026-07-21, by one engineer, from a plain console. This is a consumer measurement, not a lab paper: no repeats, no statistics beyond what pgbench prints, and the per-10-second progress lines are our stability evidence.
- The 44 GB Hetzner write summary was lost with scrollback and is quoted as ~5,000, bracketed by its progress lines and the 128-client run on the same data. Every other number is a full pgbench final block.
- The machines differ where the providers differ: Hetzner ships 2x the RAM on a 2021 CPU; ServersCamp ships faster 2024 cores and a replicated disk. Prices as configured on 2026-07-21, VAT excluded, screenshots kept. A buyer cannot normalize any of this away, so neither did we.
- Network paths are each provider's out-of-the-box defaults: public IPs within one DC on Hetzner (private networks are available with extra setup), the default private network on ServersCamp. The latency difference is part of both products as delivered.
- Both 2-vCPU client VMs ran near 100% CPU on the hottest read points, so the in-RAM read ceilings are partly client-bound, symmetrically: same client shape on both sides.
- The ServersCamp stand physically ran a 150 GB W4 volume (headroom for the 88 GB point: peak usage was 107 GB); the quoted check prices the 160 GB the workload actually calls for, matching Hetzner's included capacity. W2/W3 classes would be cheaper but their 0.5-1 GB/s throughput caps sit below the 1.4 GB/s bulk-load peaks we measured, so W4 is the right class.
- PostgreSQL 18.4 out of the PGDG box on both sides, configured by the same public pgtune formula from each machine's own RAM and cores. No per-side tuning of any kind.