AWS Auto Scaling Groups, explained for Hetzner users

Hetzner Cloud has no auto scaling group. What each part of an AWS ASG does, and what Hetzner has in its place: a snapshot, a load balancer, an API, or nothing.

Author
Published
Last updated
Tags
explainer, hetzner, autoscaling, aws

Hetzner Cloud has no auto scaling group. On AWS, an Auto Scaling group (ASG) is one object that keeps a set of identical servers between a minimum and a maximum, replaces the ones that fail a health check, and changes their number when a metric crosses a rule. Hetzner has most of the materials such a group is made of: snapshots, a load balancer with health checks, labels, hourly billing and an API. It does not have the group: nothing on Hetzner holds the count, changes it, runs the steps around adding or removing a server, or replaces a server that stops answering.

Each part of an Auto Scaling group is explained below, next to what Hetzner has in its place. AWS facts are from AWS’s documentation, Hetzner facts from Hetzner’s documentation and support, as of September 2026.

What is an AWS Auto Scaling group?

An Auto Scaling group is a set of EC2 instances, AWS’s name for virtual servers, managed as one unit. You give it a launch template, which describes a new instance; a minimum and a maximum; and a desired capacity, the number to run now. AWS then runs a loop: it compares the instances in the group with the desired capacity and launches or terminates instances until they match. An instance that fails its health check is terminated and replaced by the same loop.

Scaling policies move the desired capacity, health checks decide which instances stay, and lifecycle hooks, cooldowns and warm-up control the timing. The group itself costs nothing; you pay for the instances and for the CloudWatch alarms its policies use.

What are the Hetzner names for the AWS building blocks?

AWS Hetzner Cloud
EC2 instance Server
Instance type Server type (CX23, CAX21, CPX22, CCX13, …)
Amazon Machine Image (AMI) Image: a snapshot of your own server, or a system image
Region Network zone (eu-central, us-east, us-west, ap-southeast)
Availability Zone Location (fsn1, nbg1 and hel1 in eu-central)
VPC and subnet Network and subnet
Security group Firewall
Tags Labels
Elastic Load Balancing, target group Load balancer, with its services and targets
CloudWatch metrics Metrics endpoints of servers and load balancers
IAM credentials Project API token, Read or Read & Write

Two differences matter for scaling. A Hetzner location is a separate site: the three locations of eu-central are Falkenstein and Nuremberg in Germany and Helsinki in Finland, and a load balancer takes targets from every location of its network zone and from no other. And labels do more than AWS tags: load balancer targets and firewalls can both be defined by a label selector, so a new server with the right labels joins the balancer and gets its firewall rules without another API call.

Which parts of an Auto Scaling group does Hetzner have?

The sections after the table explain each row.

Auto Scaling group part On Hetzner Cloud
Minimum, maximum, desired None; labels let you count servers
Launch template None stored; each create call carries the recipe
AMI A snapshot, for the same CPU architecture only
Health checks The load balancer’s check: stops traffic, replaces nothing
Load balancer attachment Label selector targets; no drain setting
Lifecycle hooks None; your script is the lifecycle
Cooldown and warm-up None
Scaling policies Metrics only; no metric alarms, no policies
Scheduled actions None; a cron entry
Instance refresh None; surge and remove, or rebuild in place
Termination policy None; delete protection blocks every delete
Availability Zones Locations of one network zone; spread placement groups
Mixed instances, Spot None; a sold-out server type fails to create
Warm pools None; a powered-off server is billed in full

What is a launch template, and what replaces it on Hetzner?

A launch template is the recipe for a new instance: the AMI, the instance type, the network and security groups, the SSH key, user data, an IAM role and tags. It is versioned, and the group uses a set version, or whichever is the default or the latest. A change affects only the instances launched after it.

Hetzner stores no recipe. Each server create request carries all of it (image, server_type, location, ssh_keys, user_data for cloud-init, networks, firewalls, placement_group, labels), so the template lives in whatever sends the request; keep it in one file under version control. The AMI’s counterpart is a snapshot of a server’s whole disk, billed per GB per month, which boots only servers of the same CPU architecture: an x86 snapshot (CX, CPX, CCX) does not boot an Arm server (CAX). Snapshots have no versions, so point new servers at a snapshot ID, never at “the newest snapshot”.

What do minimum, maximum and desired capacity mean?

The desired capacity is the number of instances the group should run now; the minimum and the maximum are limits no policy crosses. When an instance disappears, the group launches another without anyone having to notice.

On Hetzner the only count is the number of servers you created. Nothing compares it with a target, and a deleted server stays deleted. Labels make a count possible: give each member the same label, such as role=web, and list the members with hcloud server list -l role=web. Keeping the count in range, and restoring it after a loss, is the loop you build; How to autoscale a web application on Hetzner Cloud without Kubernetes builds it by hand.

How does an Auto Scaling group decide an instance is unhealthy?

By default, from EC2 status checks: the instance must be running and pass AWS’s checks of the instance and its host. You can add the load balancer’s health checks, and since August 2026 EC2 can also send an HTTP or HTTPS request to the application every 60 seconds. A grace period, 300 seconds by default when the group is created in the console, spares an instance that is still booting. An unhealthy instance is terminated and replaced; an instance maintenance policy can launch the replacement first.

On Hetzner the load balancer’s health check is the only signal that knows about your application. It checks each target with a TCP connection or an HTTP request, optionally over TLS, every 3 to 60 seconds, with a timeout of 1 to 60 seconds and 1 to 5 retries, and a new target gets no traffic until it passes (Hetzner support, September 2026).

There it stops: the balancer routes around a failed server and replaces nothing. Hetzner looks after the machine, moving a server to another host for maintenance or a hardware fault when it can, with the same IP addresses, but the server’s status in the API (running, off) says whether the machine is on, not whether your application answers. Replacing a server whose application has stopped is yours to build, with a floor of two servers so that one carries the load in the meantime.

What are lifecycle hooks, and what replaces them on Hetzner?

A lifecycle hook pauses an instance on its way in, before it enters service, or on its way out, before it is terminated, so that your code can install something, register it, copy logs or finish a job. The instance waits until your code answers CONTINUE or ABANDON, or until the timeout, one hour by default, runs out.

Nothing on Hetzner starts or stops servers by itself, so there is nothing to hook into; your script is the lifecycle. On the way in: create the server, let cloud-init or your deploy run, add it as a target, wait until it is healthy, and give up after a deadline. On the way out: remove the target, wait, shut down, delete. That wait is a setting on AWS, the target group’s deregistration delay, 300 seconds by default. The Hetzner Load Balancer has none: open connections continue for up to five minutes after a target is removed, and no signal says when they have finished (Hetzner support, September 2026). Never delete a server that is still a target; deletion cuts every connection at once.

What is the difference between cooldown and warm-up?

Both keep the loop from reacting to its own last move. A cooldown pauses simple scaling policies after an action, 300 seconds by default. A warm-up leaves a new instance out of the group’s metrics until it has settled, so a server that is still booting at near-zero CPU does not drag the average down; the group’s default warm-up is off until you set it, and then applies to target tracking, step scaling and instance refresh.

Hetzner has neither, because it has no policy to pace. Any loop you write needs both: without a warm-up it counts a booting server’s idle CPU and scales in, and without a cooldown it adds and removes servers in turn.

How does an Auto Scaling group decide when to scale?

Through three kinds of scaling policy, plus schedules and forecasts:

  • Target tracking holds a metric near a value, such as average CPU at 50%; AWS creates and manages the CloudWatch alarms.
  • Step scaling reacts to an alarm you create, with a larger change for a larger breach.
  • Simple scaling makes one fixed change per alarm, then waits out the cooldown.
  • Scheduled actions set the minimum, maximum or desired capacity at a given time, once or on a recurring schedule.
  • Predictive scaling forecasts load from the group’s history and adds capacity ahead of it.

Hetzner has the metrics and none of the decisions. The API returns CPU, disk and network per server, and open connections, connections per second, requests per second and bandwidth per load balancer. CPU comes back as a sum over the server’s vCPUs, 100 per vCPU, not as the 0–100% figure CloudWatch reports (our measurement on a CX23, September 2026), so divide it by the vCPU count before comparing it with a threshold. There is no memory metric without an agent of your own, no metric alarm and no policy, and every read counts against the project’s limit of 3,600 API requests per hour. The policy is code you write, and whatever it does, a missing or stale sample must stop a decision: an empty answer from a rate-limited call is not zero load.

What is an instance refresh?

An instance refresh replaces a group’s instances in batches to roll out a new AMI or template. By default it keeps 90% of the group healthy while it works; it launches before it terminates when you set that minimum to 100%, and it can pause at checkpoints, skip instances that already match and roll back.

Hetzner has no rolling replacement, and there are two ways to build one. Surge and remove: create a server from the new snapshot, wait until the load balancer reports it healthy, then drain and delete one old server, and repeat. Or rebuild in place: the rebuild action rewrites a server’s disk from a new image; everything on the disk is lost and the server is off while it runs, so take it out of the load balancer first. Surging pays for an extra server and never lowers capacity; rebuilding pays nothing extra and lowers capacity by one server at a time. A rebuild also keeps the old price of a server ordered before 15 June 2026, which a delete loses.

Which instance does an Auto Scaling group remove first?

On scale-in, the default termination policy keeps the Availability Zones balanced, then picks instances on an outdated launch template, then the one closest to its next billing hour, then one at random. Scale-in protection exempts chosen instances, though not from a health-check replacement or a manual termination.

On Hetzner the server that goes is whichever your script picks, and three facts should shape the pick:

  • Hetzner bills per started hour, capped at the monthly price. “Closest to the next billing hour”, a rule that per-second billing made of little use on EC2, is exactly right here: a server deleted a few minutes into an hour has already paid for that hour.
  • An older server can be cheaper. A server created before 15 June 2026 keeps its old price until it is deleted or rescaled, while a new one of the same type costs more. It should never be the one to go.
  • Delete protection makes the API refuse to delete a server until the flag is lifted. It is the closest thing to scale-in protection, and stricter, since it stops your own deletes too.

When should you not rebuild an Auto Scaling group on Hetzner?

When your load is flat. If your busiest hour is close to your average, a group that grows and shrinks saves nothing; run one size up, with a second server for failures. The calculator shows where that line is for your server type and traffic.

When you run many services with different needs. A group scales one kind of server for one service. Many services sharing servers, or scheduling rules between them, is what Kubernetes is for; on Hetzner that means a cluster you run, with the Cluster Autoscaler’s Hetzner provider adding and removing nodes.

When the application keeps state on its disk. A group assumes any server can be deleted. Move the database, sessions and uploads off it first, as in step 1 of the hand-built autoscaling guide.

And we would not run the cron-job version of this loop in production. Without a health deadline, a drain and a check that it deletes only servers it created, it will one day delete the wrong one.

Where Hetscale fits

Hetscale adds the missing group to the Hetzner servers you already run: a node group with a minimum and a maximum, a template and a pinned release for every new node, your load balancer’s health check as the only sign that a node is ready, a drain before every delete, a replacement started beside a failed node, and a logged reason for every action. It calls the Hetzner API in your project and never sits in your traffic path, and it starts read-only, recording for 14 days what it would have done with your real load. The concepts page defines each of these terms; if you already run identical servers behind a Hetzner load balancer, the onboarding case for that setup shows what is left to do.

Frequently asked questions

Does Hetzner Cloud have auto scaling? No: no group, no scaling policy and no replacement of failed servers. You can build the loop on the Hetzner API, run Kubernetes with the Cluster Autoscaler’s Hetzner provider, or use a control plane that calls the API for you.

Does Hetzner bill per second like EC2? No. Hetzner bills servers per started hour, capped at the monthly price; EC2 bills most instances per second, with a one-minute minimum. A Hetzner server that runs for 61 minutes is billed for two hours, so time removals to the hour.

What happens when a Hetzner server type is sold out? The create call fails with resource_unavailable; CX and CAX types were out of stock in EU locations at times in September 2026. Hetzner does not fall back for you: try another location in the same network zone, then another type of the same CPU architecture.

Does Hetzner have Spot Instances or warm pools? No Spot market. And a powered-off server is billed like a running one until it is deleted, so a pool of stopped servers costs full price.

See what Hetscale would have done with your real data — connect read-only, get your report in minutes.

Connect read-only