I moved two servers, one from Linode and the other from DO to Hetzner a few months ago, with similar savings. The best part was that the two servers had tens of different sites running, implemented in different languages, with obsolete libraries, MySQL and Redis instances. A total mess. Well: Claude Code migrated it all, sometimes rewriting parts when the libraries where no longer available. Today complex migrations are much simpler to perform, which, I believe, will increase the mobility across providers a lot.
I’m formulating plans to switch from AWS to Hetzner. Amazon gets you by charging high prices (sometimes 20x more than competitors) and forcing you to make long-term commitments in order to get the prices to somewhere more reasonable. Then they make it exorbitantly expensive to migrate your data anywhere else. It’s a very customer-hostile approach that I’m tired of at this point.
Amazon might think that they’re locking people in with the egress fees. But they’re also locking people out. As soon as you switch one part to a competitor, the high egress forces you to switch over everything.
It’s going to be complicated to switch, but it’s made easier by the fact that I didn’t fall into the trap of building my platform on Amazon-specific services.
Every time I see this kind of article, no one really bothers about sb/server redundancy, load balancers, etc. are we ok with just 1 big server that may fail and bring several services down?
You saved a lot of money but you'll spend a lot of time in maintenance and future headaches.
This is something we've[0] done a number of times for customers coming from various cloud providers. In our case we move customers onto a multi-server (sometimes multi-AZ) deployment in Hetzner, using Kubernetes to distribute workloads across servers and provide HA. Kubernetes is likely a lot for a single node deployment such as the OP, but it makes a lot more sense as soon as multiple nodes are involved.
For backups we use both Velero and application-level backup for critical workloads (i.e. Postgres WAL backups for PITR). We also ensure all state is on at least two nodes for HA.
We also find bare metal to be a lot more performant in general. Compared to AWS we typically see service response times halve. It is not that virtualisation inherently has that much overhead, rather it is everything else. Eg, bare metal offers:
- Reduced disk latency (NVMe vs network block storage)
- Reduced network latency (we run dedicated fibre, so inter-az is about 1/10th the latency)
- Less cache contention, etc [1]
Anyway, if you want to chat about this sometime just ping me an email: adam@ company domain.
Hard to read this article as it was written by Claude as a report after the migration that Claude did for you.
If an llm helped you migrate and save this much money, kudos. But if you decide to write about it at least proof read it and remove redundant parts and llm storytelling.
The migration sharing is admirable and useful teaching, thank you!
I see the DigitalOcean vs Hetzner comparison as a tradeoff that we make in different domains all day long, similar to opening your DoorDash or UberEats instead of making your own dinner(and the cost ratio is similar too).
I work in all 3 major clouds, on-prem, the works. I still head to the DigitalOcean console for bits and pieces type work or proof of concept testing. Sometimes you just want to click a button and the server or bucket or whatever is ready and here's the access info and it has sane defaults and if I need backups or whatnot it's just a checkbox. Your time is worth money too.
I use and love Hetzner as well. But you have to go into it eyes open. Concrete example - a month ago I was notified that network infra my systems ran over was going down for maintenance. Public link: https://status.hetzner.com/incident/ff8335b8-6fda-4370-8431-...
So, for me that was a production DB, fairly low usage but still. In the end I judged that it was going to take so much time to work around the outage that I just planned "maintenance downtime" myself and took it offline for a couple of hours until they finished.
Now, could I have architected better? No doubt. But it's a good reminder of what you're paying for and where the differences emerge in practise. AWS may be an overcomplicated, expensive mess - but I've literally never had any service of theirs go down for maintenance for any reason. Outages, sure, but taking things down for routine maintenace? Unheard of at AWS.
For me the formula is - I do whatever I want for my stuff, but if it's someone else's business, I use AWS.
What are you doing for DB backups? Do you have a replica/standby? Or is it just hourly or something like that?
Because with a single-server setup like this, I'd imagine that hardware (e.g. SSD) failure brings down your app, and in the case of SSD failure, you then have hours or days downtime while you set everything up again.
A few months ago, I looked into AWS alternatives for my small SaaS side project. My main motivations were to save money and maybe support some EU cloud providers. At first, I planned to go with Hetzner and accepted that I would need to do a lot of things myself.
However, the dealbreaker for me was that Hetzner IPs have a bad reputation. At work, I learned that one of the managed AWS firewall rules blocks many (maybe all) of their IPs.
I can’t even open a website hosted on a Hetzner IP from my work laptop because it’s blocked by some IT policy (maybe this is not an issue for you if you are using CloudFlare or similar).
I've read online that the DDoS protection is very bad as well.
So in the end, I picked DO App Platform in one of the EU regions. Having the option to use a managed DB was a big plus as well.
Yeah, well be careful of Hetzner, I used to love them but I just migrated away. They just shut all all of our VMs over a $36 billing dispute. (~30 VMs we were using for our CI/CD pipeline) We provided them evidence with records of the payment in totality from our bank, they refused to look at it / discuss the dispute, even when we were communicating urgently and just ultimately shut off all our access. We're on Scaleway now.
If you’re migrating a large MySQL database and you’re not
using mydumper/myloader, you’re doing it the hard way.
If you aren't using xtrabackup you are doing it wrong. I recently migrated a database with 2TB of data from 5.7 to 8.4 with about 15 seconds of down time. It wouldn't have been possible without xtrabackup. Mysqldumper requires a global write block, I wouldn't call blocking writes for hours a "zero downtime migration".
In the big corporate world, this would be a $600m budget, creating multiple VPs, thousands of positions, multi-cloud and multi-dc kubernetes, tons of highly paid consultants, the migration would take 9 - 12 years, create so many success stories, lessons learnt, promotions, etc etc.
I know they've been bought out by Akamai or whatever but I've been using Linode for over 10 years and I still go to them if I need a VPS. I don't have extreme needs, but they seem to be always improving or adding features comparable to other providers and the UI is consistent so I don't see a reason to change. Any time there has been an issue they've migrated me to a new host automatically without even needing to do anything. I combine it with Dokploy now and just deploy most of my projects via Docker Compose and private GitHub repos.
I used to like Vultr because it was a cheaper Digital Ocean, still with a great-looking UI (if not better).
Now, prices are so bad that I have to choose between a bare metal server with 500 GB of SSD storage, 16-core CPU and 16 GB of RAM with OVH or a VM with 1/10 of that with Vultr.
It doesn't make any sense.
Also, Vultr has the nasty policy of topping your account $100 whenever you run out of money, even if your server is $3/month.
Last weekend, I transferred a handful of personal projects and my monthly expense for hosting went from $500 to $100, for vastly superior servers.
I've had excellent experiences with Percona xtrabackup for MySQL migration and backups in general. It runs live with almost no performance penalty on the source. It works so well that I always wait for them to release a new matching version before upgrade to a new MySQL version.
I migrated from Google Cloud to Hetner beginning of March. I currently have about 9 vms running and I pay a around 130 euro per month. There are very little other fees and generous freemiums for things like networking and storage. I have 3 projects, one LB, a handful of storage buckets, and a private network in one of the projects. That 130 is for everything. Their 40% price increase kicked in shortly after I signed up. It's still very affordable and good value. Their support was very helpful when a few days in I requested additional server quota.
The flip side is technical limitations and reliability. We've had a few network glitches. The vm boot disks are unencrypted (not ideal). And a few other things. Do your homework before you migrate. Most of these things you can DYI around.
I managed the whole migration via Codex orchestrating my Ansible scripts. It made fast work out of figuring out how to do NAT in Hetzner private networks and a few other hairy issues that would have otherwise derailed me for a bit. I got the whole migration completed in two days.
You get what you pay for with Hetzner and it is good value. But if you need more than they offer, you might want to look at other companies. They scale by keeping things simple. This is my second time with Hetzner. We used them around 2013 for a bit. I had six bare metal servers at the time for something like 300/month in total.
Just watch out Hetzner don’t fail to take a payment from you from their end then proceed to flag your account for non-payment all while communicating absolutely nothing about this to you arriving at the conclusion they will delete all your servers and ban your account and identity from ever using them again.
Happened to me.
I now advise people to avoid clown-led services like Hetzner and stick to more reputable, if not as cheap, options.
And DigitalOcean customer support is non-existent. I had a mail server down and they cut service instead of trying to contact me in any other way. But worse, when they do that, they immediately destroy your data without any possibility to restore. Or at least that's what they told me with their bog standard, garbage support replies. I was a customer for nearly a decade. After it happened, I realized that never would have happened on GCP, AWS, etc. Because they take billing seriously with multiple contact info, a recovery period, etc. All the things a company would be expected to do to maintain good relationships with customers during a billing issue that lasts a few weeks. That was a couple of years ago, so maybe they fixed some stuff. But the complete lack of support and unprofessional B2B practices was an eye opener.
DigitalOcean just absolutely is just not an enterprise solution. Don't trust it with your data.
Oh, and did I mention I had been paying the upcharge for backups the entire time?
Really interesting sharing, thanks! Why lower the TTL to 300 instead of something like 60 or 30, to make the switch even faster? The nameservers were DO's, so they should've been more than able to handle the increased load.
BTW, I've been a client of Hetzner (Cloud, Object Storage, and Storage Box) for a few years now, very happy with them!
> The key: proxy_ssl_verify off — the new server’s SSL cert is valid for the domain, not for the IP address. Disabling verification here is fine because we control both ends.
Not really, a MITM could do anything here. It's not very likely to happen here, but I think this comment shows a misunderstanding of what certificates and verification does.
I had my fair share of Hyperscaler -> $something_else migrations during the past year. I agree, especially with rented hardware the price-difference is kind of ridiculous.
The issue is though, that you loose the managed part of the whole Cloud promise. For ephemeral services this not a big deal, but for persistent stuff like databases where you would like to have your data safe this is kind of an issue because it shifts additional effort (and therefore cost) into your operations team.
For smaller setups (attention shameless self-promotion incoming) I am currently working on https://pellepelster.github.io/solidblocks/cloud/index.html which allows to deploy managed services to the Hetzner Cloud from a Docker-Compose like definition. E.g. a PostgreSQL database with automatic backup and disaster recovery.
As such, I doubt the noted price reduction is reproducible. Combine this with Hetzner's sudden deletions of user accounts and services without warning, and it's a bad proposition. Search r/hetzner and r/vps for hetzner for these words: banned, deleted, terminated; there are many reports. What should stun you even more about it is that Hetzner could ostensibly be closely spying on user data and workloads, even offline workloads, without which they won't even know who to ban.
The only thing that Hetzner might potentially be good for is to add to an expendable distributed compute pool, one that you can afford to lose, but then you might as well also use other bottom-of-the-barrel untrustworthy providers for it too, e.g. OVH.
The "Hetzner is 5-10x cheaper" framing is real but the comparison that actually matters is egress, not compute. A $5 DO droplet and a €4 Hetzner CX22 are both fine for a side project. What kills you on AWS/GCP at small scale is the per-GB egress - once I was pulling ~300GB/mo out of an eu-west-1 ELB and the egress line was 6x the EC2 line on the bill. Moving the same workload to Hetzner or even a single Fly.io region dropped it by >80% without touching the app.
One thing people skip: you also lose AWS's managed failure modes. Managed Postgres, VPC peering, IAM roles on instance metadata - you now own all of that. For a solo project or small team that's fine (rsync + pg_dump | pg_restore has worked for 20 years). For anything with on-call rotations it's a meaningful shift.
Great read. I also recently moved everything over from DO to Hetzner for https://tempmaildetector.com across different regions*, and greatly simplified the server infra in the process. The other added benefit is that the resources available on each server are so great in comparison to DO that there’s plenty of room to grow vertically before even taking into account the additional horizontal scaling we can use thanks to the load balancing in place.
So a big win win all round. So good to see European providers are finally having their moment.
* I wish there were even more available and not sold out regions across Europe.
I wish we had something like Hetzner dedicated near us-east-1.
They do offer VPS in the US and the value is great. I was seriously looking at moving our academic lab over from AWS but server availability was bad enough to scare me off. They didn't have the instances we needed reliably. Really hoping that calms down.
It's tough to work with these publicly traded companies. They need to boost prices to show revenue growth. At some point, they become a bad deal. I've already migrated from DO. Not because of service or quality, but solely because of price.
They're great but I wish Hetzner had a US (or CA) east coast presence, the latency of going across the ocean is really troublesome. They have some presence for their cloud offering, so they at least have some experience with the idea.
I did the same this year. I really liked Digital Ocean though, compared to more complex cloud offerings like AWS. AWS feels like spending more for the same complexity. At least DO feels like it does save time and mental band width. Still though, the performance of cloud VPS is abysmal for the price. I'm now on Hetzner + K3's plus Flux CD (with Cloudflare for file storage (R2) and caching. I run postgres on the same machine with frequent dump backups. If I ever need realtime read replicas, I'll likely just migrate the DB to Neon or something and keep Hetzner with snapshots for running app containers.
> Old server nginx converted to reverse proxy We wrote a Python script that parsed every server {} block across all 34 Nginx site configs, backed up the originals, and replaced them with proxy configurations pointing to the new server. This meant that during DNS propagation, any request still hitting the old IP was silently forwarded. No user would see a disruption.
What was the config on the receiving side to support this? Did you whitelist the old server IP to trust the forwarding headers? Otherwise you’d get the old server IP in your app logs. Not a huge deal for an hour but if something went wrong it can get confusing.
Congrats on doing this successfully, but your setup is amateur. This would have been infinitely easier if you were using IaC (Terraform/Ansible), containerized applications (that you're not already doing that is madness), and had a high-availability cluster setup in place already. It sounds like avoiding downtime is important to you, yet there's no redundancy in the existing stack at all, and everything is done by hand.
This isn't something others should use as an example.
Given the premise that zero day exploits are going to be frequent going forward, I feel like there is a new standard for secure deployment.
Namely, all remote access (including serving http) must managed by a major player big enough to be part of private disclosure (e.g. Project Glasswing).
That doesn't mean we have to use AWS et al for everything, but some sort of zero trust solution actively maintained by one of them seems like the right path. For example, I've started running on Hetzner with Cloudflare Tunnels.
DO is so expensive compared with others; one of my clients insisted on using it as they found aws too costly; I got them over to Hetzner after a few months saving them 28k/month. I have no clue why people bother with DO vs AWS if they want to spend that kind of cash on hosting. I host million$ SaaS on Bunny.net and Hetzner for less than $200/mo; will never go back to the overcharging companies; and this is trivial to rsync migrate to whatever other provider too.
Great migration execution. The nginx reverse proxy method during DNS propagation is a smart way. we utilize a comparable approach when transitioning workloads across Kubernetes clusters but the traffic management occurs at the ingress controller level with weighted routing. I am wondering if you thought about containerizing any part of this stack during the transition or if the decision to use bare metal was deliberate in order to maintain a manageable migration scope???
does anyone else start to wonder about these companys issuing vps/online space with no hardening and no warning
you can basically go on hetzner and spin up a vps with linux that is exposed to the open internet with open ports and user security and within a few hours its been hacked, there is no like warning pop up that says "if you do this your server will be pwnd"
i especialy wonder with all the ai provisioned vps and postgres dbs what will happen here
I started with DO in 2013 when they offered 20GB SSD, 512MB RAM for $5/mo. For some reason I paid no VAT then, but I do now. Their $4/mo option now is still 512MB, still 1 vCPU, but 10GB SSD. So it's like the last decade of technological progress with regards to RAM, CPU and storage that should either lead to price cuts/spec bumps didn't happen. And yeah, DO got expensive before AI bought up all the memory.
430 comments
if agents eat that glue, the moat gets thin fast.
How deep does this go?
Amazon might think that they’re locking people in with the egress fees. But they’re also locking people out. As soon as you switch one part to a competitor, the high egress forces you to switch over everything.
It’s going to be complicated to switch, but it’s made easier by the fact that I didn’t fall into the trap of building my platform on Amazon-specific services.
You saved a lot of money but you'll spend a lot of time in maintenance and future headaches.
For backups we use both Velero and application-level backup for critical workloads (i.e. Postgres WAL backups for PITR). We also ensure all state is on at least two nodes for HA.
We also find bare metal to be a lot more performant in general. Compared to AWS we typically see service response times halve. It is not that virtualisation inherently has that much overhead, rather it is everything else. Eg, bare metal offers:
- Reduced disk latency (NVMe vs network block storage)
- Reduced network latency (we run dedicated fibre, so inter-az is about 1/10th the latency)
- Less cache contention, etc [1]
Anyway, if you want to chat about this sometime just ping me an email: adam@ company domain.
[0] https://lithus.eu
[1] I wrote more on this 6 months ago: https://news.ycombinator.com/item?id=45615867
I see the DigitalOcean vs Hetzner comparison as a tradeoff that we make in different domains all day long, similar to opening your DoorDash or UberEats instead of making your own dinner(and the cost ratio is similar too).
I work in all 3 major clouds, on-prem, the works. I still head to the DigitalOcean console for bits and pieces type work or proof of concept testing. Sometimes you just want to click a button and the server or bucket or whatever is ready and here's the access info and it has sane defaults and if I need backups or whatnot it's just a checkbox. Your time is worth money too.
So, for me that was a production DB, fairly low usage but still. In the end I judged that it was going to take so much time to work around the outage that I just planned "maintenance downtime" myself and took it offline for a couple of hours until they finished.
Now, could I have architected better? No doubt. But it's a good reminder of what you're paying for and where the differences emerge in practise. AWS may be an overcomplicated, expensive mess - but I've literally never had any service of theirs go down for maintenance for any reason. Outages, sure, but taking things down for routine maintenace? Unheard of at AWS.
For me the formula is - I do whatever I want for my stuff, but if it's someone else's business, I use AWS.
Because with a single-server setup like this, I'd imagine that hardware (e.g. SSD) failure brings down your app, and in the case of SSD failure, you then have hours or days downtime while you set everything up again.
However, the dealbreaker for me was that Hetzner IPs have a bad reputation. At work, I learned that one of the managed AWS firewall rules blocks many (maybe all) of their IPs. I can’t even open a website hosted on a Hetzner IP from my work laptop because it’s blocked by some IT policy (maybe this is not an issue for you if you are using CloudFlare or similar).
I've read online that the DDoS protection is very bad as well.
So in the end, I picked DO App Platform in one of the EU regions. Having the option to use a managed DB was a big plus as well.
Now, prices are so bad that I have to choose between a bare metal server with 500 GB of SSD storage, 16-core CPU and 16 GB of RAM with OVH or a VM with 1/10 of that with Vultr.
It doesn't make any sense.
Also, Vultr has the nasty policy of topping your account $100 whenever you run out of money, even if your server is $3/month.
Last weekend, I transferred a handful of personal projects and my monthly expense for hosting went from $500 to $100, for vastly superior servers.
The flip side is technical limitations and reliability. We've had a few network glitches. The vm boot disks are unencrypted (not ideal). And a few other things. Do your homework before you migrate. Most of these things you can DYI around.
I managed the whole migration via Codex orchestrating my Ansible scripts. It made fast work out of figuring out how to do NAT in Hetzner private networks and a few other hairy issues that would have otherwise derailed me for a bit. I got the whole migration completed in two days.
You get what you pay for with Hetzner and it is good value. But if you need more than they offer, you might want to look at other companies. They scale by keeping things simple. This is my second time with Hetzner. We used them around 2013 for a bit. I had six bare metal servers at the time for something like 300/month in total.
Moving away from the US also felt great.
Happened to me.
I now advise people to avoid clown-led services like Hetzner and stick to more reputable, if not as cheap, options.
Sounds like from the requirement to live migrate you can't really afford planned downtime, so why are you risking unplanned downtime?
DigitalOcean just absolutely is just not an enterprise solution. Don't trust it with your data.
Oh, and did I mention I had been paying the upcharge for backups the entire time?
BTW, I've been a client of Hetzner (Cloud, Object Storage, and Storage Box) for a few years now, very happy with them!
> The key: proxy_ssl_verify off — the new server’s SSL cert is valid for the domain, not for the IP address. Disabling verification here is fine because we control both ends.
Not really, a MITM could do anything here. It's not very likely to happen here, but I think this comment shows a misunderstanding of what certificates and verification does.
The issue is though, that you loose the managed part of the whole Cloud promise. For ephemeral services this not a big deal, but for persistent stuff like databases where you would like to have your data safe this is kind of an issue because it shifts additional effort (and therefore cost) into your operations team.
For smaller setups (attention shameless self-promotion incoming) I am currently working on https://pellepelster.github.io/solidblocks/cloud/index.html which allows to deploy managed services to the Hetzner Cloud from a Docker-Compose like definition. E.g. a PostgreSQL database with automatic backup and disaster recovery.
As such, I doubt the noted price reduction is reproducible. Combine this with Hetzner's sudden deletions of user accounts and services without warning, and it's a bad proposition. Search r/hetzner and r/vps for hetzner for these words: banned, deleted, terminated; there are many reports. What should stun you even more about it is that Hetzner could ostensibly be closely spying on user data and workloads, even offline workloads, without which they won't even know who to ban.
The only thing that Hetzner might potentially be good for is to add to an expendable distributed compute pool, one that you can afford to lose, but then you might as well also use other bottom-of-the-barrel untrustworthy providers for it too, e.g. OVH.
One thing people skip: you also lose AWS's managed failure modes. Managed Postgres, VPC peering, IAM roles on instance metadata - you now own all of that. For a solo project or small team that's fine (rsync + pg_dump | pg_restore has worked for 20 years). For anything with on-call rotations it's a meaningful shift.
So a big win win all round. So good to see European providers are finally having their moment.
* I wish there were even more available and not sold out regions across Europe.
They do offer VPS in the US and the value is great. I was seriously looking at moving our academic lab over from AWS but server availability was bad enough to scare me off. They didn't have the instances we needed reliably. Really hoping that calms down.
Nice to see it used _twice_ :D
> Cloud providers are expensive for steady-state workloads.
Asking the obvious question: why not your own server in a colo?
> Old server nginx converted to reverse proxy We wrote a Python script that parsed every server {} block across all 34 Nginx site configs, backed up the originals, and replaced them with proxy configurations pointing to the new server. This meant that during DNS propagation, any request still hitting the old IP was silently forwarded. No user would see a disruption.
What was the config on the receiving side to support this? Did you whitelist the old server IP to trust the forwarding headers? Otherwise you’d get the old server IP in your app logs. Not a huge deal for an hour but if something went wrong it can get confusing.
This isn't something others should use as an example.
https://slitherworld.com
My foray into multiplayer games.
Namely, all remote access (including serving http) must managed by a major player big enough to be part of private disclosure (e.g. Project Glasswing).
That doesn't mean we have to use AWS et al for everything, but some sort of zero trust solution actively maintained by one of them seems like the right path. For example, I've started running on Hetzner with Cloudflare Tunnels.
Anyone else doing something similar?
- reduce dns ttl (if not doing an ip swap)
- rsync website files
- rsync /etc/letsencrypt/ ssl certificates
- copy over database (if writes don't happen often and database is small enough, this can be done without replica, just go read_only during migration)
- test new server by putting new ip in local /etc/hosts
- turn off cron on old server
- convert old server nginx to reverse proxy to new server
- change dns (or ip swap between old and new server)
- turn on cron on new server
you can basically go on hetzner and spin up a vps with linux that is exposed to the open internet with open ports and user security and within a few hours its been hacked, there is no like warning pop up that says "if you do this your server will be pwnd"
i especialy wonder with all the ai provisioned vps and postgres dbs what will happen here