My Go-To Providers · Part 2 of 2Running a $5/month VPS on AWS will cost you closer to $35 before you’ve added a static IP, decent storage, and a data transfer allowance that doesn’t make you sweat every time someone downloads a PDF. I found that out the hard way. Hetzner was the correction.
Why I Left the Big Cloud Pastures
I don’t have a philosophical objection to AWS or Google Cloud. They’re remarkable pieces of engineering, and if you’re running a Fortune 500 company’s compliance-heavy infrastructure, maybe you need that ecosystem. But I’m a self-taught guy running his own projects from a home office in the Deep South, and the big cloud providers are priced for enterprises, billed like lawyers, and documented like they assume you already work there.
What I needed was simple: reliable compute, sensible storage, predictable pricing, and a provider that wouldn’t nickle-and-dime me every time a packet crossed an invisible billing boundary. Hetzner, a German company with data centers in Nuremberg, Falkenstein, and Helsinki, gave me all of that at prices that still make me double-check the invoice every month like it must be wrong.
The price comparison isn’t even close. A CX22 on Hetzner, 2 vCPUs, 4 GB RAM, 40 GB NVMe, 20 TB of monthly traffic, runs about ā¬4.35/month at time of writing. Find me that on AWS without a reserved instance commitment, a spreadsheet, and three hours you’ll never get back. You can’t. That price delta isn’t a rounding error. It compounds across every project, every experiment, every “let me just spin something up and see” moment. Hetzner made it cheap enough that I actually try things instead of talking myself out of them.
The Servers I Actually Use
I run a few different tiers depending on what a project demands, and Hetzner’s lineup maps cleanly onto how I think about workloads.
For lightweight apps and side projects:
The CX22 is my default starting point. New project, quick proof of concept, something I want to leave running but don’t expect to hammer; CX22. It handles a Node or Go app, a small Postgres instance, and Caddy as a reverse proxy without breaking a sweat. If traffic picks up, I resize the instance through their Cloud Console in about 90 seconds. That’s not marketing. I’ve done it at 11pm when something unexpectedly made the front page of a forum.
For production apps that matter:
I step up to the CX32 (4 vCPU, 8 GB RAM) or CX42 depending on the memory profile. If I’m running something with a database that needs room to breathe, or a background job queue that competes with the web process, I want that headroom. Still wildly affordable compared to equivalent specs elsewhere.
For dedicated workloads:
Hetzner also offers dedicated root servers through their Robot platform, bare metal machines you lease outright. I’ve used these for heavier compute tasks where I don’t want to share a hypervisor with anyone else. The AX series (AMD Ryzen) offers ridiculous performance per euro for the right workload. It’s not my everyday setup, but it’s there when I need it, and the pricing is still grounded in reality.
Storage volumes are a separate line item, persistent block storage you can attach and detach from instances. I use these for anything I don’t want baked into the instance itself: database data directories, uploaded files, backups. Snapshots are cheap enough that I automate them without guilt.
Provisioning Without the Ceremony
One of the things I appreciate about Hetzner is that the Cloud Console is genuinely usable. It’s not trying to be a product unto itself. You pick a location, pick a server type, paste in your SSH key, optionally select a cloud-init script, and you’re SSH’d into a fresh Ubuntu box in under 60 seconds. That’s it. No wizard with seven screens, no IAM role to configure before you can even see the pricing.
I provision most servers with a simple cloud-init script that handles the basics: update packages, install Docker and Docker Compose, set up UFW with sane defaults, configure my default user, drop in a cron job for unattended security upgrades. Claude Code (which I covered in Part 1) helped me build out that script to a point where I trust it. I’d prompt-engineered through enough edge cases that it now handles the things I used to have to remember manually.
For anything beyond a single server, I’ve started using Terraform with Hetzner’s provider. The workflow is straightforward: define the resource, terraform apply, done. The state file lives in a private S3-compatible bucket (Hetzner has their own object storage too, Hetzner Object Storage, priced predictably, of course). I’m not running a Kubernetes cluster or anything that requires serious orchestration at my scale. Docker Compose and a couple of well-placed shell scripts gets the job done, and Terraform keeps the infrastructure definition honest.
The Helsinki Question: Tradeoffs Worth Naming
Here’s the honest part that I think a lot of “Hetzner is great” write-ups skip over: my servers are in Europe, and most of my users are in North America. That latency is real, and I want to be straight about it.
A request from Seattle to Helsinki will see somewhere in the neighborhood of 100-160ms of baseline round-trip latency depending on routing. For a lot of use cases, that’s not a problem in practice. Here’s why:
- Cloudflare sits in front of everything I run (more on that in Part 3). Static assets, cached responses, and edge logic all serve from a PoP close to the user. The request only goes all the way to Helsinki when it needs to, authenticated API calls, database writes, things that can’t be cached.
- Async and background work doesn’t care. A job that kicks off when a user takes an action, sending an email, processing an upload, running a calculation, the user isn’t waiting on the TCP round trip for that.
- My apps aren’t high-frequency trading systems. If you’re building something where 100ms is a user-perceptible difference that changes behavior, you’ve outgrown this conversation. Most CRUD apps, SaaS tools, and content sites are not in that category.
That said, I’ll be honest: if I had a project where the North American latency was genuinely hurting me, I’d look at Hetzner’s Ashburn, Virginia location (they’ve expanded their US presence) or I’d route specific latency-sensitive endpoints differently. The solution exists. It just hasn’t been necessary yet.
The other overseas consideration is data residency. European data protection requirements apply to servers hosted in the EU. For most of what I build, this is fine. I’m not storing sensitive personal data at volume. But it’s a real thing to be aware of, and I’d rather name it than pretend the question doesn’t exist.
What You Give Up and Why I’m Still Here
Hetzner doesn’t have a managed Kubernetes offering that competes with EKS. Their managed database offering is solid but younger than AWS RDS. Their support is responsive but not the kind of 24/7 enterprise SLA that comes with a four-figure monthly commitment. Their ecosystem of integrations isn’t as vast. If any of those gaps are blockers for you, you know where to find AWS.
But for a self-taught operator running a real production stack solo? Hetzner gives me reliable compute at prices that let me experiment freely, a provisioning experience that respects my time, and infrastructure that has, genuinely, never given me a reason to distrust it. The servers run. The network is fast. The bills are small. That’s most of the job.
Next up in Part 3, I’ll walk through Cloudflare, which is really the piece that makes Helsinki feel a lot closer to wherever your users are. The edge layer, the caching rules, the DNS management, and why I’ve handed Cloudflare the keys to every front door I run. It’s the part of this stack I’d have the hardest time replacing.