Skip to content

Blog ·

Hetzner Cloud: the available flag predicts nothing

Hetzner calls a server type unavailable, then delivers it four times; calls another available, then refuses it. What we measured, and what to read instead.

By Provibr

If you build a server-type picker for Hetzner Cloud and you filter it on the catalogue's available flag (which is the obvious thing to do, and what we started with), you will hide machines your customers can order and offer machines Hetzner will refuse. The flag does not predict whether an order will succeed, in either direction. This is what we measured, and what to read instead.

Everything below was measured against the live Hetzner Cloud API while building the Provibr integration, with an ordinary API token.

The two contradictions

We took two server types and did the same experiment with each: read what the catalogue said, then actually place the order.

Hetzner Cloud exposes its catalogue through two API resources: GET /server_types, whose entries carry a per-location available flag, and GET /datacenters, which lists the server types available and supported in each datacentre.

cx23 said no, and was delivered four times. In GET /server_types, cx23 had available: false in all three German and Finnish locations (fsn1, nbg1, hel1), and it appeared in no datacentre's available list at all. By every reading of the catalogue, you cannot order it. We ordered it in nbg1 anyway: POST /servers returned HTTP 201, and the machine was delivered. We repeated that four times.

cax11 said yes, and was refused. The ARM part cax11 appeared in the available list for both nbg1 and hel1. By the catalogue, you can order it. We tried, in nbg1: POST /servers returned HTTP 422, "unsupported location for server type".

So the flag was wrong in both directions on the same afternoon: a false that delivers and a true that refuses.

The two sources disagree with each other, too

It is not only that the flag disagrees with reality: the catalogue disagrees with itself. GET /server_types (the per-location available flag) and GET /datacenters (the per-datacentre available list) describe the same server-type-in-location pairs, and they do not match. We compared them across the whole catalogue: of 114 server-type-and-location pairs, the two sources disagreed on 20. Roughly one pair in six. Whichever source you pick, you are picking a number that the other Hetzner endpoint contradicts.

Why: it is a stock meter, not a capability flag

We were reading available as if it were a static fact about what exists ("does this type run in this datacentre"), and it is not. It is a live inventory gauge, and it moves on a minute scale.

Measured with a single token, the same day, twenty-one minutes apart:

text
15:08 UTC   cx23 fsn1: false   nbg1: false   hel1: false
15:29 UTC   cx23 fsn1: true    nbg1: true    hel1: true

Three flags flipped in twenty-one minutes, with no other change anywhere in the catalogue: the other 111 pairs stood still. Two different tokens read the same values at the same moment, so it is not a per-token cache. available is Hetzner reporting, right now, whether there is free capacity of that type in that location to hand out. It is genuinely useful information, but it answers "is there stock this minute", not "can my customer buy this", and those are different questions once you remember that stock refills.

That also explains an old contradiction in our own notes, where one measurement said a type was unavailable and an earlier one said it was available. Both were right, at their own moment. There was never a stable answer to disagree about.

What this breaks if you trust it

A plan picker that filters on available inherits the flag's flicker. A machine type winks out of your product catalogue for the twenty minutes Hetzner happens to be low on stock, then winks back, so a customer refreshing your order page sees the plan they wanted disappear and reappear for no reason they can see, and a plan they could have ordered (a false that would have delivered) is hidden from them the whole time. You have built a storefront whose shelves rearrange themselves while the customer is looking at them.

Worse is a batch job that reads the catalogue once and caches it. It freezes one instant of a moving meter and treats it as the shape of the product for hours.

What to read instead

The honest arbiter of "can this be ordered" is the order. There is no catalogue field that answers it, because capacity is not a property of the catalogue.

  • Do not filter your plan picker on available. Offer the server types you have chosen to sell, in the locations you sell them, and let the order be the thing that can fail.
  • Handle the 422 at order time. "unsupported location for server type" is a real, actionable answer (it means pick another location or another type), and it arrives exactly when you can do something about it, rather than as a flag you cached an hour ago.
  • If you want to show a capacity hint, read available at the moment of rendering and label it as "in stock now", not as whether the plan exists. Never let it remove a plan.

Provibr does exactly that: the server type comes from the plan you defined, the order is what can fail, and a 422 becomes a clear "that type is not available in that location right now, choose another" rather than a plan that silently vanished.

It is not the only Hetzner field that reads like an answer and isn't

The same caution applies to two more fields we measured, because the underlying lesson (a populated value is a claim, not a fact) is the same one.

  • progress: 100 sits next to status: "error". A create can report 100% progress and a failed status at the same time. Progress is not success; read the status.
  • GET /servers?status=off does not return a stopped machine (measured three times). If you list machines with a status filter, you drop exactly the ones that are switched off.

None of these is a bug you would find by hand: you would order the machine, see it work, and move on. They are the things automation has to know, and the reason a "just call the API" integration takes longer to get right than it looks.

Measured against the live Hetzner Cloud API in August 2026 with an ordinary API token. The catalogue structure was read from docs.hetzner.com on 26 August 2026. No account or token identifiers appear here; cx23, cax11 and the location codes are Hetzner's own public product names.

Start with one host and one agent

Create an account, install the agent with a single command and connect your first Proxmox host. The trial runs for 14 days and asks for no payment details.