Two cloud bills walked into Hetzner, and one much smaller bill walked out. In October 2025, the Scottish co-op Digital Society published the full before-and-after of migrating its SaaS and side services off AWS and DigitalOcean onto Hetzner Cloud: $559.36 a month down to $132.96, while provisioned capacity more than tripled from 12 to 44 vCPUs. The writeup names every line item on both sides, which makes it something rare in cloud-migration discourse — a savings claim you can actually audit.
So let's audit it. Here is the bill, in full, in the first screen:
| Before | After | |
|---|---|---|
| AWS (ECS Fargate + RDS + ALB + NAT, two environments of the tap SaaS) | $449.50/mo (August peak) | — |
| DigitalOcean (DOKS nodes + block storage + load balancer) | $109.86/mo (July peak) | — |
| Hetzner Cloud (ARM servers + LB + volumes + object storage) | — | $132.96/mo |
| Total | $559.36/mo | $132.96/mo (−76%) |
| Provisioned capacity | 12 vCPU / 24 GB RAM | 44 shared ARM vCPU / 88 GB RAM |
Two honesty notes before the thesis, because the writeup discloses both and the audit should too. First, the two "before" peaks are from different months — DigitalOcean peaked in July, AWS in August — since the two legs migrated at different times. Second, Hetzner invoices in euros, so the $132.96 is a converted figure; the writeup doesn't state the exchange rate. And the capacity row counts vCPUs, not benchmarked throughput — 44 shared Ampere cores are not 3.7 Fargate-equivalents by any benchmark, a qualifier Section 2 makes precise.
The thesis, split the way the numbers demand: three on-bill drivers explain the full 76% — per-unit compute roughly 10x cheaper, a managed-primitive long tail (NAT gateways, load balancers, RDS) that collapses to flat-rate pricing, and egress that stops being a metered line item at all. Two more technologies, Talos Linux and CloudNativePG, explain why the labor side didn't eat the savings — but they are off-bill viability, not part of the 76%, and this post keeps them there.
TL;DR — where the 76% comes from:
- Compute is the biggest line: one always-on 2vCPU/4GB Fargate container cost "just over $70/month"; the equivalent Hetzner ARM slice costs single-digit euros. Serverless per-second pricing punished always-on workers hardest.
- The long tail is the stealth line: NAT gateways (~$33/mo each before a byte flows), ALB hourly-plus-LCU metering, and RDS instance-plus-storage-plus-I/O never appear in the "Fargate is $70" mental math, but they all land on the invoice.
- Egress is the growth line: AWS charges $0.09/GB while Hetzner bundles 20TB per server with €1/TB overage — for a data-intensive SaaS, the marginal cost per query effectively vanishes.
- What they still rent: load balancers, block volumes, object storage, networks, firewalls. The migration is "same managed primitives, one-tenth the meter," not a return to racking servers.
- What made self-managing viable: Talos Linux removed the OS-maintenance toil and CloudNativePG replaced RDS without hiring a DBA — labor savings, kept strictly separate from the bill math.
Compute: the $70 container vs the €6 server
Digital Society's SaaS, tap, is a data-intensive product: complex queries over gigabytes of data in seconds, built on Rust with Apache Arrow and DataFusion. Minimum viable performance needed around 2 vCPUs and 4GB RAM per worker, ideally more. On AWS Fargate that container costs just over $70 a month. Two such workers, plus smaller web instances, across two environments — before a single load balancer, database, or NAT gateway enters the picture.
The Hetzner side of that comparison is a shared-vCPU ARM cloud server (Ampere-based CAX class): 2 vCPUs and 4GB RAM for around €6 a month. Same nominal envelope, roughly a tenth of the meter. Multiply across two workers, web instances, two environments, and the monitoring stack absorbed from DigitalOcean, and compute alone explains the majority of the delta.
Fargate deserves a fair hearing, because the lesson is about workload shape, not vendor villainy. Per-second pricing scales down beautifully — a minimal 0.25-CPU task costs around $10 a month — but it also scales up linearly for workloads that never scale to zero. Always-on workers paying per-second for every second of the month buy serverless flexibility and consume none of it. Steady-state always-on is precisely where flat-rate slices win, and tap is that shape twice over with two environments.
Now the qualifier the headline owes you. Hetzner's 44 vCPUs are shared ARM cores — burstable slices of a host CPU, not dedicated threads — versus Fargate's dedicated x86 allocation. vCPU count is capacity-on-paper, not throughput parity, and no honest read equates "3.7x the vCPUs" with "3.7x the performance." What makes the count meaningful is the workload: a Rust/DataFusion stack is famously compute-efficient, and the team's post-migration monitoring confirmed they got the performance they needed. For bursty or latency-sensitive workloads, shared cores would be the first line item to interrogate.
The long tail, both legs
Nobody's mental model of their AWS bill survives contact with the invoice, and this migration shows why. The $449.50 AWS leg was never "containers plus a database." It was two worker containers and web instances plus an Application Load Balancer (hourly charge plus per-LCU metering), an RDS instance (instance hours plus storage plus I/O plus backups), NAT gateways at $0.045 per hour — about $33 a month each, per availability zone, before a single byte flows — plus $0.045 per gigabyte processed through them, plus what the writeup wearily calls "a long tail of peripheral services, as is the AWS way."
Each of those primitives is individually reasonable. Together they are a ~40%-of-compute surcharge on a small deployment that a Fargate-vs-VPS comparison never captures. The NAT gateway is the purest example: a highly-available setup wants one per AZ, so a small three-AZ footprint pays roughly $100 a month for the privilege of letting private subnets reach the internet, then pays per gigabyte on top. On Hetzner, the equivalent — cloud networks plus free firewalls, with a flat-rate load balancer in front — has no per-byte processing meter at all.
The DigitalOcean leg deserves its own line-item destination, because "AWS-to-Hetzner" headlines erase it. The $109.86 bought a DOKS cluster — DigitalOcean's managed Kubernetes, free control plane, paid nodes, block storage, and load balancer — hosting lightweight services: the epcdata.scot site, Umami analytics, OpenObserve telemetry, and Uptime Kuma monitoring. In the migration, that entire leg dissolved into spare capacity on the Hetzner Talos cluster. There was no "DO replacement" line item because consolidation was the replacement: one cluster with 44 vCPUs absorbs what previously needed a whole second control plane and node pool. That is a genuine savings mechanism — fleet consolidation — and it only shows up if you track the DO leg to its destination instead of rounding it into "AWS."
On the database line, RDS was replaced by CloudNativePG — a declarative Postgres operator on the cluster's existing nodes, so the database's compute cost is zero marginal dollars on top of nodes already paid for. The writeup's requirements read like an RDS checklist — monitoring, automated failover, seamless upgrades, scheduled backups — and CloudNativePG ticks each box with Postgres-native semantics including point-in-time recovery. The remaining database cost is block storage under the data directory. This is the cleanest "same primitive, one-tenth the meter" swap in the migration, and it keeps going mainstream: Percona added commercial CloudNativePG support in September 2026, a signal that operator-run Postgres has crossed from brave to boring.
Egress stops being a line item
For most migrations this section would be a footnote. For a data-intensive SaaS, it's the growth story. AWS charges $0.09 per gigabyte for internet egress (first 10TB each month); every query result tap ships to a user is metered at that rate. Hetzner Cloud servers include 20TB of outgoing traffic per server each month, with overage at €1 per terabyte — roughly a 90x cheaper per-unit rate past an allowance most small SaaS products never exhaust.
The strategic difference is in the marginal math. On AWS, 10x query growth is 10x egress spend — success taxes itself. On Hetzner's allowance model, the same growth is free until 20TB per server, then €1/TB. The writeup doesn't break out exact egress spend, but for a product whose purpose is shipping query results, per-gigabyte to effectively-flat is the difference between "growth needs a pricing conversation" and "growth needs nothing."
Object storage tells the same story in miniature. AWS S3 charges $0.023/GB-month for storage plus $90/TB for egress; Hetzner's S3-compatible object storage starts around €5 a month including 1TB of storage and 1TB of egress. Same API shape, same "dumb bytes over HTTP" semantics — the migration kept its S3-compatible tooling and just pointed it at a cheaper endpoint. When people say "egress is the real lock-in," this is the receipt: not the storage, the $90/TB exit toll Hetzner prices at €1.
What they still rent
The most instructive part of the $132.96 is what it still contains, because it demolishes the "self-hosting means racking servers" strawman. The Hetzner bill buys managed load balancers, block storage volumes, S3-compatible object storage, private networks, and firewalls — nearly the same primitive catalog as the AWS side, minus RDS and NAT gateways, at roughly a tenth of the meter. Nobody racked anything. Nobody negotiated a colo contract. The team traded one managed cloud for a cheaper managed cloud and replaced two managed services (RDS, DOKS control plane) with operators.
That framing — same managed primitives, one-tenth the meter — is the honest version of the story, and it poses the real question for platform teams: if your PaaS runs on owned or flat-rate infrastructure, can you tell it with your own bills attached? A Render-compatible platform on Cluster API and Hetzner-shaped pricing should show tenants the same decomposition — compute at cost, primitives at flat rates, egress effectively free — instead of re-metering every primitive at a markup. The migration proves the economics; the PaaS question is who passes them through.
The two things that made self-managing viable (off-bill)
None of the above explains who pages when Postgres fails over at 3 AM — and that labor question is where self-hosting economics usually die. Digital Society's answer has two parts, both explicitly labor-side, neither counted in the 76%.
The first is Talos Linux as the node OS: an immutable, API-driven operating system built solely to run Kubernetes, with no SSH daemon, no shell, and no package manager. Nodes are managed declaratively — machine configuration applied via API, and the OS converges itself — which deletes entire categories of fleet toil: no SSH key rotation, no configuration drift from ad-hoc logins, no snowflake nodes, upgrades as atomic image swaps rather than package surgery. The writeup is candid that running their own Kubernetes "wasn't a decision taken lightly" after years of managed offerings; Talos is what made it a decision rather than a dare. The savings here are headcount-shaped — the OS-maintenance hours that never get scheduled — which is precisely why they don't appear in a bill comparison and precisely why they matter to a small team.
The second is CloudNativePG, covered above on the bill side but equally important on the labor side: declarative failover replicas, scheduled backups, and configuration overrides in Kubernetes manifests next to the workloads that consume them. No DBA retainer, no runbook for "RDS minor version upgrade weekend," no 3 AM failover procedure that lives in one person's head. The operator is the runbook, versioned in git and reconciled by controllers — the same operational model as everything else on their cluster, which is the deeper point. Self-managing stops being scary when every layer, OS to database, speaks the same declarative language.
Rounding out the stack: Ingress NGINX for in-cluster routing, ExternalDNS for DNS, cert-manager for TLS, and Terraform plus Helm plus GitHub Actions for IaC and deployment automation. Unglamorous, standard — and operable by the same small team that previously clicked through two cloud consoles.
The honest caveats
A 76% figure without caveats is marketing. With them, it's engineering. The writeup discloses four, and each one narrows where the result generalizes.
Hetzner network zones are not availability zones. The team initially equated Hetzner locations within the eu-central network zone to AWS AZs — same zone, private networking between them — then discovered significant inter-location latency through post-deployment monitoring. Multi-location workloads suffered. The fix was a single location (Nuremberg) with placement groups spreading VMs across physical hosts. That is a real resilience downgrade versus three-AZ AWS: placement groups survive host failure, not datacenter failure. If your threat model requires surviving a facility outage, this migration's topology doesn't serve you, and no discount rate changes that.
Shared vCPUs are not dedicated cores. Restated from Section 2 because it belongs in the caveats too: the 44-vs-12 count compares burstable shared ARM slices to dedicated Fargate allocations. It held up for an efficient Rust workload with monitoring to prove it. A latency-sensitive or single-thread-bound workload should read "3.7x the vCPUs" as unproven until benchmarked, not as headroom banked.
The migration labor was underestimated. Docker-based did not mean trivially portable: the ECS-to-Kubernetes move wasn't the container config, it was the deployment automation around it — scripts gathering config from GitHub into CloudFormation had to be re-thought as Kustomize glue between repo config and manifests. The team is happy with the result (non-sensitive config now lives reviewable in the repo), but the work took longer than expected. Budget the glue, not just the containers.
Credits are a trap with a timer. The whole AWS chapter started with a generous $1,000 startup-credit package that let the team experiment without watching the meter — then ran out in under six months, leaving a $449.50 monthly habit built at $0 marginal perceived cost. There is a general lesson here for bootstrapped teams: architect on credits as if you're already paying the invoice, because the invoice arrives exactly when you're busiest shipping.
The break-even math for your team
So when does the self-hosted math win, and when doesn't it? The writeup's numbers imply a clean decision rule with three variables.
Self-hosting wins when your workloads are steady-state and always-on (flat-rate slices beat per-second metering), data-heavy on egress (allowance models beat $0.09/GB), and tolerant of single-facility topology (one location plus placement groups). Digital Society is three for three: always-on query workers, query results as the product, and a SaaS that survives on host-level redundancy. The 76% is what three-for-three looks like.
It loses — or at least shrinks toward parity — when any variable flips. Spiky or zero-to-scale workloads genuinely benefit from serverless scale-to-zero; a regulated workload needing multi-AZ failover can't accept the topology downgrade; and a team without Kubernetes fluency pays the migration-labor line item at full price instead of amortizing a decade of experience. The writeup's authors had ten years of Kubernetes behind them. Price your own learning curve honestly before projecting their 76% onto your team.
The deeper takeaway is for platform builders, not just migrators. Every line item in this audit — flat-rate compute, unmetered egress, operator-run databases, declarative node OSes — is a primitive a self-hosted PaaS can pass through to tenants instead of re-metering. The migration proves the economics exist. The open question is which platforms productize them.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



