Back to all posts

Published April 5, 2026

Hetzner billing surprises: what AWS, Azure, and GCP habits get wrong

Piotr HajkowskiBy Piotr Hajkowski

Migrating to Hetzner is usually a positive surprise — the price-to-performance ratio is hard to argue with. The billing surprises come later, when habits from AWS, Azure, or GCP produce results that don't match the mental model.

On AWS, cost broadly follows activity. Stop an EC2 instance, the compute charge stops. Take an EBS snapshot, you pay for what changed. Attach an Elastic IP to a running instance, you pay nothing for the IP itself. On Hetzner, cost follows existence. If a resource is in your project, it accrues a charge, regardless of whether it is running, attached, or doing anything useful.

This is not a flaw in Hetzner's design. It reflects a deliberate infrastructure philosophy: when you create a resource, Hetzner allocates real hardware. That allocation persists until you explicitly release it. Understanding this distinction is what separates predictable Hetzner bills from surprising ones. After the April 1, 2026 price adjustment, each of these patterns now costs meaningfully more than it did in Q1.


Powered-off servers are billed at the full server rate

The AWS assumption: stopping an EC2 instance stops the compute charge. You pay for EBS storage while the instance is off, not for vCPUs or RAM.

Hetzner reality: powering off a server changes nothing about your invoice. The server, its disk, and its allocated IP remain reserved. You are billed at the full server rate until you delete the server, not stop it, delete it.

Hetzner's billing FAQ is unambiguous: "Until you, the customer, delete your servers, we will bill you for them, regardless of their state. This is because, internally, we allocate full resources to servers regardless of their power state."

The common failure mode: an engineering team in Nuremberg or Helsinki snapshots a server before a risky deployment, powers it off "temporarily" during a sprint, and forgets it for six weeks. At the CCX13 rate of €15.99/mo in Germany and Finland (EUR billing), that forgotten instance costs €192/year without processing a single request.

Stopping a server is a valid operational step; it doesn't mean you're paying less. If a server is no longer needed, delete it. Take a snapshot first if you may need to restore it; you can create a new server from that snapshot when the time comes.


IPv4 addresses are billed per address, per hour — even when nothing is attached

Since February 2024, Hetzner bills primary IPv4 addresses separately from the servers they belong to. Every primary IPv4 costs approximately €0.50/mo whether or not it is assigned to a running server.

The first trap: IP addresses that outlive their servers. When you delete a server, Hetzner does not automatically delete its IP. If you keep the address "in case you need it," and never get back to it, you pay €0.50/mo indefinitely per orphaned address. On infrastructure that regularly cycles servers, such as CI/CD pipelines, staging environments, and short-lived test instances, unattached IPs accumulate without drawing much attention until the invoice arrives.

The second trap: floating IPs. Floating IPv4 addresses cost €3.00/mo and are billed whether or not they are attached to a server. AWS moved to charging for all public IPv4 in February 2024 ($0.005/hr, or $3.65/mo per address), so per-IP billing regardless of attachment is no longer unique to Hetzner. What differs is the failure mode: a Hetzner floating IP reserved as a high-availability failover address and never actually triggered costs €36/year for the privilege of being available.

At 50 servers with one primary IPv4 each, that is €25/mo in IP charges before a single byte of compute. Add two unattached floating IPs and the line item grows further, entirely from addresses that are not delivering value.


Backups cost 20% of the server price, regardless of how much data is on the disk

The AWS assumption: backup cost correlates with storage consumed. AWS EBS snapshots are incremental and charged per GB of stored data.

Hetzner reality: enabling automatic backups adds a flat 20% surcharge to the server's price. A CCX13 at €15.99/mo costs €3.20/mo to back up whether the disk is 2% full or 95% full. For that price you get seven backup slots retained on a rolling schedule.

This model catches teams that enable backups by default on all servers as an organizational policy. A fleet of ten CCX13 development servers runs €159.90/mo in compute and an additional €31.98/mo in backup charges, for environments that in most cases don't need nightly backups at all.

The 20% now applies to a higher base price; backups on a CCX13 cost €3.20/mo, up from €2.40/mo. That difference compounds across a fleet where backups were enabled and never reviewed. The April 2026 price increase post covered this in the context of general cost increases; the underlying pattern is a billing model misunderstanding, not just a price change.


Snapshots capture the full disk state, not just what changed

The AWS assumption: EBS snapshots are incremental by design: each snapshot stores only the blocks that changed since the previous one. A 100 GB disk with 8 GB of real data produces a snapshot sized closer to 8 GB, and a second snapshot of an idle server costs almost nothing.

Hetzner reality: Hetzner snapshots are full images of the disk, not incremental deltas. Each snapshot captures the complete disk state at that point in time, compressed. A second snapshot of the same server is approximately the same size as the first; there is no deduplication across snapshot versions.

Pricing is €0.0143/GB (up from €0.0110/GB), charged on the actual compressed image size. A 160 GB allocated disk with 40 GB of real data might produce a snapshot of 40–50 GB, costing roughly €0.57–0.72/mo per snapshot. That number looks manageable until you account for three months of deployment snapshots with no retention policy: ten snapshots at €0.65/mo each is €6.50/mo for disk images that almost certainly no longer reflect a useful point in time.

The practical rule: take snapshots with intention, and delete them on a schedule. Unlike AWS, there is no incremental cost reduction for keeping fewer recent snapshots. Each one is independently sized.


Cloud servers cannot be rescaled down below their initially provisioned size

The AWS/Azure/GCP/OCI assumption: compute and storage scale independently. On EC2, EBS volumes are separate resources — changing from a t3.large to a t3.medium leaves your root volume untouched. On Azure, VM resize docs state explicitly that "the OS and data disks are not affected." On GCP, machine type and persistent disk are managed through separate commands. On OCI, shape changes affect OCPUs and memory while "volume attachments remain the same." Across all of them, boot disk size is fully decoupled from compute tier.

Hetzner reality: CPU and RAM rescales are reversible on Hetzner. The disk is not. Hetzner's own documentation is direct: "Rescaling to a plan with a smaller disk is not possible, regardless of how much storage you are actually using."

If you resize from a CCX23 (80 GB disk) to a CCX33 (160 GB disk) to handle a temporary traffic peak, and later try to scale back down to the CCX23, you cannot; the disk is now too large. There is no automated escape. Hetzner will not restore a snapshot to a server whose disk is smaller than the snapshot's source disk — the restore fails at creation regardless of how little data was actually on the disk. The only path out is a manual migration: provision a new smaller server, copy your data across with rsync or equivalent tooling, and decommission the old one. That works only if your actual data fits within the target disk, and it requires planned downtime.

Hetzner provides a "CPU and RAM only" resize option that keeps the disk at its current size and preserves the downgrade path. It is easy to overlook when the default includes a disk upgrade. If you are resizing for a temporary workload and expect to scale back down, check that option explicitly.

The compounding effect: a larger disk means a larger snapshot. Upsizing from an 80 GB disk to a 160 GB disk doubles the snapshot cost indefinitely, for every snapshot taken from that point forward, even if the extra disk space is never used.


Dedicated servers ordered through Robot carry a one-time setup fee

Hetzner has two separate ordering systems that work differently: the Cloud Console (console.hetzner.cloud) and Robot (robot.hetzner.com). Cloud servers have no setup fee; you pay hourly from the moment the server is provisioned, and it is ready within seconds. Dedicated servers ordered through Robot are different.

Robot dedicated servers are physical machines allocated specifically to you. They bill hourly (Hetzner introduced hourly billing for dedicated servers in 2024), but most carry a one-time setup fee charged at provisioning. That fee appears on your first invoice before any monthly usage accrues. Hetzner raised setup fees in February 2026 citing hardware acquisition costs.

The setup fee is most consequential for GPU machines, and the numbers are not small relative to the monthly rate. The GEX44 — Hetzner's entry-level GPU dedicated server costs €252.64/mo. Its setup fee is €314.16, which is 124% of the monthly cost. Order a GEX44, run it for one hour, then cancel: the invoice is €314.56. That is the floor, regardless of how briefly you use it.

The AWS/GCP habit that breaks here: spinning up a GPU instance on AWS (g5.xlarge, p3.2xlarge) incurs no setup charge; you pay per hour from the first second, and you can terminate after an hour having spent only that hour's rate. On Hetzner Robot, the hardware is physically dedicated and configured for you, and that one-time provisioning cost applies whether you keep the machine for an hour or a year.

The pattern becomes expensive when that AWS instinct repeats. A team that provisions a GEX44, runs a training job, terminates it to avoid paying for idle time, then provisions it again the following week has paid two setup fees — €628.32 — before a full month of usage has accrued. The setup fee applies at each new provisioning.

The visibility problem compounds this. Robot dedicated server charges do not appear in the Hetzner Cloud Console's usage preview, which covers only cloud resources. The actual invoice arrives on the billing date assigned to the account, which can fall in the middle of the following month. A team cycling through multiple create-and-terminate runs has no in-console signal of the accumulating setup fees until the invoice lands.

Two things reduce the setup fee risk. Hetzner's Server Auction (Serverbörse at robot.hetzner.com/order/market) lists pre-provisioned dedicated servers without setup fees — the GEX44 appears there occasionally, and ordering through the auction avoids the setup charge. Availability is not guaranteed and configurations may not match exactly what you need. Second, all dedicated servers provisioned through Robot include unlimited traffic on a 1 Gbit uplink, which is a meaningful advantage over cloud servers with their per-server monthly traffic quotas.

Provisioning time is also different from cloud: dedicated Robot servers take 1–3 business days, not the seconds that cloud servers require.


There is no managed NAT gateway — a server with a public IP is open to the internet by default

The AWS/GCP assumption: VMs in private subnets reach the internet through a managed NAT gateway — a cloud service that provides outbound-only connectivity without assigning a public IP to each VM. The VM itself is never directly reachable from the internet, even while making outbound requests.

Hetzner reality: Hetzner has no managed NAT gateway. Servers can be created without public IPs and placed on a private Cloud Network, but a private-only server has no outbound internet access by default. To give a server outbound internet access, you either assign it a public IPv4 address or build your own NAT setup: a separate server with a public IP that routes traffic for the private servers behind it, with IP forwarding and iptables MASQUERADE rules configured by hand. Most teams new to Hetzner skip the NAT architecture and assign public IPs.

The billing consequence of a public IP is €0.50/mo per address. The security consequence is less obvious: a Hetzner server with a public IP has all ports open to the internet unless a Cloud Firewall is explicitly attached. Cloud Firewalls are opt-in, and are not applied at server creation by default.

A server with no firewall — or one where a container runtime has bypassed host-level firewall rules by writing directly to iptables — can be compromised and used as part of a botnet without the owner noticing. The bill shows up as a traffic overage. EU cloud servers include 20 TB of outbound traffic per month; overages are billed at €1/TB per server. A CX32 running personal projects recently generated a $188 invoice for 176 TB of outgoing traffic in a single month, 560 Mbit/s sustained for 30 days, entirely from a compromised server. Hetzner sent warning emails at 75% and 100% of the included traffic quota. They went unread.

For context: 176 TB from AWS to the internet costs approximately $12,050 at standard pricing. Hetzner's per-TB rate is forgiving; an unsecured, idle server is not.

The correct setup for a server with a public IP is to attach a Cloud Firewall at creation — allowing only the ports actually needed and restricting SSH access to known IP ranges. For architectures where application servers should not be directly internet-reachable, the pattern is private-network-only servers with no public IP. If those servers need outbound internet access, route it through a dedicated egress host, a server with a public IP configured for NAT. Admin SSH access goes through a separate bastion host using ProxyJump. In small environments the egress host and bastion can be the same VM, but separating them is cleaner: the bastion should stay minimal and hardened, without extra routing responsibilities. Hetzner's tutorial How to set up NAT gateway for private Cloud Networks covers the NAT setup in full.

Running hcloud server list against hcloud firewall list shows which servers have public IPs and no firewall assigned.


What to do with this

None of these billing behaviors are hidden. Hetzner documents each one. What makes them surprises is the mismatch with habits built on other platforms, a gap that widens the more AWS, Azure, or GCP infrastructure was in your background.

The underlying habit is an existence audit, not a usage review. What is in your project that you did not consciously choose to keep? Powered-off servers, unassigned IPs, orphaned volumes, stale snapshots — none of them announce themselves. Running hcloud server list, hcloud volume list, hcloud primary-ip list, and hcloud snapshot list takes two minutes. The decision about what to keep is usually faster than that.

Two settings are worth making team defaults before the infrastructure grows: automatic backups off on non-production servers (enable explicitly for databases and stateful workloads), and Cloud Firewalls attached at creation with a minimal ruleset. Neither is hard to establish as policy; both are hard to retrofit across a fleet that's already running.

These patterns are individually minor. Left unaddressed across a team that is actively deploying and scaling infrastructure, they compound. CloudTally surfaces Hetzner spend broken down by resource type: idle servers, orphaned IPs, snapshot accumulation, and detached volumes — so these patterns become visible before the invoice, not after.