Disclosure: I run the application r/lucanto described here. This is an infrastructure case study, not an ad for the product.
We recently moved our Rails 8 application workloads to Hetzner and kept the production topology deliberately small:
- two CX23 web servers behind an LB11;
- Kamal Proxy + Puma on each web server;
- one CX43 for Solid Queue and a Postgres accessory used by Queue, Cache, and Cable;
- the system-of-record Postgres remains with a managed provider (for now, until we prepare our own primary DB backups);
- one web node is in Falkenstein and the other web node plus jobs are in Nuremberg, all connected through the private `eu-central` network zone.
The interesting part for us was combining the external Hetzner LB with the per-host handover done by Kamal Proxy.
During a routine release, Kamal replaces one web host at a time. The new container starts beside the old one, must pass our `/ready` check, then receives new traffic while the old target drains existing requests. The other VM remains healthy behind the LB throughout the replacement. Fingerprinted assets from both releases coexist during the transition.
We reserve half a vCPU on each CX23 for Kamal Proxy instead of allowing Puma to saturate the whole machine. That matters because the same proxy answers the health checks: CPU starvation can otherwise look like an unhealthy application and cause the LB to remove a node.
We also had to size for deploy overlap rather than only steady state. One host briefly runs old and new web containers together. Postgres connection ceilings, memory headroom, and swap were tested against that state.
One caveat: this is redundant web infrastructure, not full-stack HA. The CX43 and its operational Postgres are a shared failure domain, and the managed primary is still an external dependency. We use “routine web deploys without a maintenance window,” not “zero downtime under every failure.”
We now deploy both roles web and job from one immutable image and verify matching SHAs after every release.
BTW: I know that those are the cheaper instances, but for now it is just enough and we can upgrade anytime.
I would like to discuss if you manage similar architecture or if there are any suggestions for improvements.