DEV Community

Pavel
Pavel

Posted on • Originally published at hostim.dev

PostgreSQL Benchmark: AWS RDS vs Hostim vs Self-Hosted on Hetzner (2026)

Short answer first: at the same size (2 vCPU / 4 GB, PostgreSQL 16), Hostim had the fastest writes, about 2.5× the write throughput of AWS RDS db.t4g.medium and 2.1× a default self-hosted Postgres on Hetzner. Hetzner had the fastest reads, on raw per-core CPU speed. RDS was slowest or near-slowest on both, and its listed price is the smallest part of the real bill.

This post shows every number, the exact commands to reproduce them, and (because it changes the conclusion) what high availability actually costs on each platform.

Benchmarks run July 2026 on PostgreSQL 16, in a central-Europe region. Prices change often, so check each provider's live pricing page before you commit. The shape of the result changes far less than the exact numbers.


What we compared

Three ways to run a small production Postgres, all at 2 vCPU / 4 GB RAM, PostgreSQL 16, in a central-Europe region:

Offering Instance Listed price / month Replicated (failover)?
Hostim managed Postgres drp-50 (2 vCPU / 4 GB) €50 Yes, by default
AWS RDS db.t4g.medium (2 vCPU / 4 GB) ~$48 (instance only) No (single-AZ)
Self-hosted Hetzner CPX22 (2 vCPU AMD / 4 GB, shared) €19.49 No (single node)

The "replicated" column matters a lot for both price and performance. It gets its own section below.


Methodology

The goal was a like-for-like test, not a flattering one. The rules:

  • Same DB size: 2 vCPU / 4 GB on every target.
  • Same Postgres major version: 16.
  • A separate load generator per target, one network hop from the database, in the same region, never on the database box itself. Each client had 4 vCPU so the client was never the bottleneck (checked with mpstat).
  • Same workload: pgbench, scale factor 50 (about 750 MB, which fits in RAM so the test measures CPU and the commit path, not cold disk reads), 300-second runs.

Client setup:

sudo apt-get install -y postgresql-contrib nmap sysstat   # pgbench + nping
pgbench --version
Enter fullscreen mode Exit fullscreen mode

The workload, run identically against each database:

# initialise (~750 MB)
pgbench -i -s 50

# write-heavy, TPC-B-like, 4 clients, 5 minutes
pgbench -c 4 -j 4 -T 300

# read-only, 8 clients, 5 minutes
pgbench -c 8 -j 4 -T 300 -S

# single connection, write, 1 minute (isolates commit/fsync latency)
pgbench -c 1 -T 60
Enter fullscreen mode Exit fullscreen mode

Network latency was measured with a TCP ping to port 5432 (nping --tcp -p 5432) and a SELECT 1 round-trip, because ICMP is not open on every platform.

Configuration parity, stated plainly: the self-hosted Hetzner node ran stock Postgres defaults (shared_buffers 128 MB, no tuning). That is the realistic "install Postgres and go" baseline. RDS ran on its default parameter group, which AWS tunes for the instance size. Hostim runs its own managed tuning. In other words, the two managed options are tuned out of the box and the self-hosted default is not, and that difference is part of what you are comparing.


Results

All runs completed with zero failed transactions.

Write throughput (4 clients, TPC-B)

Target TPS Avg latency
Hostim drp-50 2,708 1.48 ms
Hetzner (default) 1,303 3.07 ms
AWS RDS t4g.medium 1,080 3.71 ms

Hostim did about 2.5× the write throughput of RDS and 2.1× the default Hetzner node.

Single-connection write latency (1 client)

This isolates the commit path. Every transaction waits for a WAL flush (synchronous_commit = on is the default), so it mostly measures storage fsync latency.

Target TPS Avg latency
Hostim drp-50 871 1.15 ms
AWS RDS t4g.medium 416 2.41 ms
Hetzner (default) 276 3.63 ms

Both self-hosted and RDS pay for network-attached block storage on the commit path. This is the single biggest driver of the write-throughput gap.

Read throughput (8 clients, SELECT-only)

Target TPS Avg latency
Hetzner (default) 20,068 0.40 ms
Hostim drp-50 14,333 0.56 ms
AWS RDS t4g.medium 13,261 0.60 ms

Reads scale with CPU, and the Hetzner box took this one on raw per-core AMD speed with no orchestration layer in the path. Hostim and RDS were close, with RDS last. Note that db.t4g.medium is a burstable instance: over a sustained 300-second run it can drop to its CPU-credit baseline, which is what the ~$48 tier is designed to provide. A workload that needs sustained CPU would move to an m-class RDS instance, which costs roughly twice as much.

Network latency

Target TCP RTT (avg) SELECT 1
Hostim drp-50 0.48 ms ~0.29 ms
Hetzner (default) 0.71 ms ~0.39 ms
AWS RDS t4g.medium 1.50 ms ~0.58 ms

The price you actually pay

This is where the listed numbers stop being useful.

AWS RDS: $48 is not the bill

The ~$48 is the instance only, single-AZ, on-demand. On top of that you pay, metered separately:

  • Storage: gp3 is billed per GB-month.
  • IOPS and throughput above the gp3 baseline: billed if you provision more.
  • Backups: retained backup storage beyond your volume size is billed.
  • Data transfer: egress and cross-AZ traffic are billed per GB.

One storage dropdown makes this concrete. Pick Provisioned IOPS SSD in the create-database wizard and RDS defaults to 3000 provisioned IOPS, billed per IOPS-month at about $300/month (io1 ≈ $0.10/IOPS, io2 ≈ $0.125/IOPS) on top of the instance and the GB storage. The gp3 default includes the same 3000 IOPS and 125 MB/s free up to 400 GB, so there it costs nothing. Same database, ~$300/month apart, from one dropdown.

A realistic single-AZ db.t4g.medium with a modest volume and normal traffic lands well above the sticker once storage, IOPS, backups, and egress are counted, and the exact figure changes month to month. Treat $48 as a floor, not a price. (We wrote about this metered-bill pattern in Cloud Rent in Action and Usage-Based Pricing.)

High availability changes the comparison

The results above are not apples-to-apples on resilience, and this is the important part.

  • Hostim drp-50 is replicated by default. The €50 includes a standby and automatic failover. Nothing to configure.
  • AWS RDS needs Multi-AZ for a standby with failover. Multi-AZ runs a second instance and roughly doubles the instance and storage cost. It also makes writes slower, because commits wait on the synchronous standby, so a fair, HA-to-HA comparison would put RDS writes below the single-AZ numbers measured above.
  • Self-hosted Hetzner has no failover at all on one node. To match Hostim you add a second VPS (another €20) and then build and operate the replication and failover yourself (streaming replication plus a tool like Patroni or repmgr, plus a routing layer), and you own every incident.

Normalised to "replicated Postgres with automatic failover":

Offering Roughly what HA costs / month Extra work
Hostim drp-50 €50, included None
AWS RDS Multi-AZ ~2× instance + storage, plus egress and backups None, but slower writes
Hetzner, 2 nodes ~€40 hardware You build and run failover yourself

So the €50 Hostim number already includes the thing that doubles the AWS price and turns the Hetzner option into an operations project.


Caveats

  • db.t4g.medium is burstable ARM; sustained runs can hit the CPU-credit baseline. That is the behaviour of the price-matched tier, not a misconfiguration.
  • The self-hosted node used stock Postgres defaults on purpose. Tuning shared_buffers and friends would raise its numbers, but doing that is your job when you self-host.
  • RDS was single-AZ for the raw benchmark; Multi-AZ is slower and dearer, as noted above.
  • The dataset fit in RAM (scale 50), which isolates compute. A dataset larger than RAM would put more weight on storage and widen the write gaps, not close them.
  • Architectures differ (RDS is ARM Graviton, the others x86). This is what each provider sells at this price, so it is reported as-is.

Takeaways

  • For write-heavy workloads at this size, Hostim was fastest by a clear margin, mostly due to storage fsync latency on the commit path.
  • For read-heavy workloads, a self-hosted box had the raw per-core CPU edge, if you are willing to tune it and operate it.
  • AWS RDS at the price-matched tier was slowest or near-slowest on both, and its real cost (storage, IOPS, egress, and Multi-AZ for failover) is a multiple of the listed instance price.
  • If you want replicated Postgres without running it yourself, the flat, HA-included price is the number to compare against, not the single-node sticker.

Every number above is reproducible with the commands in the methodology section. If you are still deciding between managed and self-hosted in the first place, see Self-Host Postgres or Use Supabase? and Which Database Should You Self-Host?.


A managed, replicated Postgres at a flat price

If the parts you dislike are the climbing AWS bill and the operations work of running your own failover, that is exactly what Hostim is built to avoid. Managed Postgres is replicated by default, at a flat, predictable price: drp-50 is €50/month with the standby included. There is also a free database tier to test the fit, and new projects get a free 5-day trial with no card.

👉 Spin up a managed Postgres on Hostim, free tier, no card

Last updated: 2026-07-07. Benchmarks run 2026-07-07 on PostgreSQL 16, eu-central region.

Top comments (0)