Your autoscaler asked for one more node. The API didn't return a slow price quote — it returned no capacity in this location. No retry-after header. No exception queue to join. The box was simply not for sale that day, in that region, for your account.
That is not a headline every PaaS migration guide prepares you for. The Hetzner story of 2026 so far has been about money: a 30–37% price hike on April 1, then a second hike on June 15 that pushed dedicated-vCPU CCX/CPX lines up 113–175% on top of the April increase, both blamed on the DRAM and NVMe price shock swallowing cloud margins. You can model money. What happened next you have to engineer around.
Starting June 26, 2026, Hetzner began restricting new cloud-server creation for new customers and a random subset of existing ones, citing "continuing high demand and the limited availability of required hardware components." The restriction is per-location, per-customer, and explicit in Hetzner's own FAQ: "To ensure the stability and availability of our cloud infrastructure for all customers, we reserve the right to temporarily restrict the provisioning of new cloud servers at specific locations when necessary. When this happens, cloud servers at a specific location may be temporarily unavailable to a limited group of customers." There is no request form for an exception. There is no priority allocation. The server type you scaled on last month is the same API call that fails today.
This post is the page most "self-hosting is cheaper" calculators never had: the difference between a bill that goes up and a shelf that goes empty, what concretely breaks in a Cluster-API-managed fleet when it does, and the specific deployment patterns that keep a PaaS scaling when one Hetzner location says "no stock."
The two kinds of bad news: price hikes vs. stock-outs
Cloud pricing discourse loves a percentage. Hetzner's 2026 pricing story gives you plenty:
| Event | Effective | What changed | Scale |
|---|---|---|---|
| April 1, 2026 | Announced Feb 24 | Cloud servers in Germany and Finland up 30–37% depending on tier; some dedicated lines up to 50%. CX23 entry moved €2.99 → €3.99 | Broad: every line, new and existing customers |
| June 15, 2026 | Published in pricing tables | Dedicated-vCPU CCX and AMD-shared CPX lines up 113–175% on the already-hiked price; ARM CAX and Intel CX lines up a milder ~30–38%. Example: CCX13 (2 dedicated vCPU) €15.99 → €42.99 (+169%) | Brutal but selective: the wrong family hurts most |
Both are real costs. A three-node CX22 fleet that was €12/month of compute in January can be €24–€36 after June if it sat on CCX/CPX. You recompute your default MachineDeployment instance type and move on.
A capacity restriction is not a recompute. It is a provisioning failure — the Machine resource your Cluster Autoscaler or Karpenter asked for never becomes a Node. Pods that triggered the scale-up sit Pending. Deploys that expected to land on new capacity queue. And unlike a price increase, a frustrated retry loop makes it worse: five retries against an out-of-stock location is five API errors and zero machines.
That is why this post treats them as different failure modes with different mitigations. A price hike wants a cost model. A stock-out wants a fallback topology.
What "temporarily unavailable to a limited group" actually means in practice
Hetzner's wording is precise and worth unpacking, because it determines what you can and cannot plan around:
- Per-location, not per-account ban. One customer reports
fsn1refusingCX22whilenbg1still accepts it. Another can still order inhel1. The restriction moves location by location, not as a single global flag. - Limited group, not everyone at once. Two teams on the same API with the same server type can see different outcomes the same afternoon. Random assignment is intentional — it caps contention without taking the whole region dark. It also means "my colleague can still order" is not proof you will be able to tomorrow.
- Duration is not committed. The FAQ says "temporarily" and adds "when necessary." There is no published SLA for when a location reopens to restricted accounts. In 2026's broader context that is unsurprising: the underlying cause — DRAM contract prices projected 58–63% quarter-over-quarter in Q2 2026 and 53–58% in Q1, HBM capacity crowding DDR5 supply, and component vendors prioritizing their largest hyperscaler customers — is not a Hetzner-specific outage to patch overnight. Industry trackers from TrendForce through late 2025 and into 2026 describe a sustained shortage, not a single bad week.
- No exception path. Unlike a quota-increase ticket on AWS or GCP, Hetzner's restriction page documents no form, no support escalation, and no paid priority tier to jump the queue. You wait for the location to reopen, or you land the workload elsewhere.
In CAPH terms, that means the failure is in the infrastructure provider's admission check, before Cluster API ever gets a providerID. Your HCloudMachineTemplate is valid. Your Cluster is healthy. The controller just cannot materialize the machine at that location.
What breaks in a Cluster API fleet — concretely
If your fleet's default node pool is one MachineDeployment in one location with one server type, a stock-out looks like this:
-
Cluster Autoscaler stalls. The autoscaler sees
Pendingpods, asks CAPH for a newMachinein the configuredHCloudMachineTemplate(saynbg1/CCX13), and gets an API error. It backs off, retries, and fails again. Pods remainPendingand your Horizontal Pod Autoscaler has nowhere to place new replicas. From the app's perspective the platform has capacity — from the provider's perspective it does not. -
Rolling updates cannot surge. A
MachineDeploymentrolling update that needs one extra replica before draining the old one will hang, because the surge replica cannot be placed. You can setmaxSurge: 0to force an in-place drain, but that trades a brief availability dip for progress — the right trade, but only if you made it before the incident. -
Karpenter's "cheapest fitting node" can still lose. A Karpenter
NodePoolthat only lists oneinstanceFamilyin onezonehas the same single-path failure. Karpenter will try the next cheapest only if you gave it a next cheapest. Without a fallback list, the pending pods stay pending and Karpenter's consolidation loop has nothing to consolidate. -
Single-region state amplifies the blast radius. A fleet that put etcd, ingress, and all workers in
fsn1because it was cheap now has no worker pool to absorb failover. The Kubernetes control plane may be HA, but no new workers materialize where they are needed. This is the same lesson hyperscaler single-AZ outages teach — a regional capacity ceiling is a regional blast radius whether the underlying cause is power, network, or inventory.
None of this corrupts data or takes the existing workload down. That is what makes it easy to overlook until it bites. The failure mode is silent starvation, not a loud crash.
The playbook: five patterns that keep a bex-style fleet scaling
The fixes are boring infrastructure patterns. That is exactly why they work.
1. Spread MachineDeployments across at least two locations
The simplest hedge is the one that would have avoided the June 26 restriction entirely for most teams: do not put every worker in the same Hetzner location.
# Two MachineDeployments, same cluster, different CAPH locations.
# If fsn1 says "no capacity," nbg1 still takes the scale-up.
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
name: workers-fsn1
spec:
replicas: 3
template:
spec:
infrastructureRef:
kind: HCloudMachineTemplate
name: workers-cx22-fsn1apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
name: workers-nbg1
spec:
replicas: 3
template:
spec:
infrastructureRef:
kind: HCloudMachineTemplate
name: workers-cx22-nbg1Pair that with the control-plane spread you should already have (kube-hetzner's multi-DC preset, or k0s-hetzner-boilerplate-multizone's three-DC HA pattern with keepalived VIP + round-robin ingress) and a single-location restriction becomes a rebalancing event, not an outage.
What to tune: keep the per-location replicas low enough that losing one location does not halve your burst capacity. For most bex-scale fleets, two locations with replicas: 3 each is the honest default; scale individual deployments rather than adding a third location on the day you need it.
2. Offer the scheduler more than one server type
The June 15 repricing made this a cost move too, but the capacity angle alone justifies it: if CCX13 is the out-of-stock SKU while CX22 or CAX11 still has inventory, a template that only knows one type cannot try the other.
For Karpenter on Hetzner (karpenter-provider-hetzner), that looks like listing multiple instanceTypes in the NodePool's requirements so the controller can pick the next fitting price:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general
spec:
template:
spec:
requirements:
- key: karpenter.hetzner.sh/instance-type
operator: In
values: [cx22, cpx22, cax11] # fallback chain
- key: topology.kubernetes.io/zone
operator: In
values: [fsn1, nbg1, hel1]For classic CAPH MachineDeployments, the same idea is two HCloudMachineTemplate objects (workers-cx22-fsn1, workers-cpx22-fsn1) and autoscaler annotations that let the Cluster Autoscaler choose between the deployments. The point is not "always pick the cheapest" — it is "never give the provider only one SKU to say no to."
3. Hold headroom — don't autoscale exactly to zero spare
A fleet that runs at 95% requested CPU cannot absorb a stock-out that coincides with a traffic spike. The autoscaler wants to add nodes exactly when the provider is least likely to have them free, because everyone else's autoscaler is asking too.
Reserve a small, always-on buffer: one extra replica per location, or a Karpenter NodePool with limits above current demand and a consolidationPolicy that only reclaims the buffer after a real idle window — not immediately. The cost of that buffer on a CX22-class node is under €5/month (pre-June it's under €3). The cost of zero headroom during a restriction is every new deploy waiting.
4. Monitor stock the way you monitor CPU
Hetzner exposes server availability per location and type in its pricing and placement APIs. The community already knows this pattern: tools like hetzner-cost-monitor and the small availability watchers that roost and similar launchers bundle query the datacenter API and alert when a type/zone comes back. Wire that into your fleet, not just your laptop:
- A cron that queries
cloud.hetzner.comlocations for your configured server types and exports a metric (hetzner_capacity_available{location, type} 0|1). - An alert that fires when your default type goes
0in your default location, so you can preemptively shift the nextMachineDeploymentrollout to the fallback before users notice pending pods. - A dashboard that graphs
Cluster Autoscalerscale-up errors byHCloudMachineTemplate— the earliest human-readable signal that a stock-out is happening.
5. Keep a second provider shovel-ready, even if you don't default to it
Every comparison on this list has treated Hetzner as the baseline precisely because it is the best list-price-per-GB deal in the EU. That is still true after two hikes — the raw box undercuts hyperscalers and most EU peers — but "best list price" and "always in stock" are independent promises.
For a CAPH fleet, the honest second target is not another Hetzner location but a second provider behind a second Cluster API provider: OVHcloud, Scaleway, or a lightweight Netcup-equivalent where the API maturity honestly permits it. The emerging pattern in the ecosystem — cluster-api-provider-scaleway adapters that join Scaleway nodes into an existing CAPH cluster, and the Virt8ra sovereign-edge testbed linking OVHcloud/Scaleway/Ionos — shows the control plane can be provider-mixed even if your default worker pool stays Hetzner. You do not need to run 50% of your fleet elsewhere to get value from the escape hatch. You need the Terraform, the ClusterClass, and the network peering proven once in staging so that a Friday-afternoon "no stock in fsn1" is a kubectl apply away from a mitigation rather than a weekend-long migration.
Be candid about the gaps: Netcup's API and footprint are thinner than Hetzner's, OVHcloud's own June-price adjustments (+9–11% in 2026) move too, and adding a provider adds operational surface. The point is not to pretend a second provider is a drop-in replacement — it is to avoid the trap of discovering the replacement cost during the incident.
Why "own the machines" still wins — even when the machine store is temporarily closed
A reasonable reader asks: if the bare-metal provider can also say "sold out," what did self-hosting buy you over a hyperscaler's equally opaque capacity allocation?
Three things, and they all compound:
You saw the boundary. Hetzner's FAQ tells you up front it may restrict provisioning at specific locations for a limited group, and the API tells you immediately when you hit it. A hyperscaler's capacity constraint — AWS's well-documented preference to prioritize its largest customers for scarce DRAM/HBM-backed instances in 2025–2026, or its single-AZ InsufficientInstanceCapacity errors that only surface when you launch — is structurally similar but disclosure-laggy: you learn you are constrained when a launch fails inside the provider's own scheduler, not at a clearly documented admission gate you can design around.
You choose the fallback. A hosted PaaS tenant waiting behind the platform's own capacity queue (the self-hosting pages that every Fly, Render, and Railway user inherits silently) cannot re-route their workload to a second Hetzner location — the platform already picked one. A CAPH fleet owner can: flip the MachineDeployment location, widen the Karpenter NodePool instance list, or shift the next scale-up to nbg1. The constraint is the same physics; the agency is different.
Your failures are uncorrelated. The H1 2026 reliability census counted 30,000+ outages across 1,000+ providers precisely because multi-tenant platforms turn one vendor's bad component batch into thousands of customers' correlated outage. A capacity ceiling on one self-owned fleet is uncorrelated with the thousand other fleets that hit theirs in a different location that week. That is not a claim that self-hosting has zero incidents — it is the observation that the shared fate domain is smaller when you drew the boundary.
Said more bluntly: no vendor escapes a hardware shortage that started in the foundries and lands in every data center. The question is whether the place you discovered the shortage is also a place you can do something about it. A single-location PaaS with no fallback list cannot. A two-location fleet with a second provider staged can.
What to do this week
If you run a Hetzner-backed fleet — bex-based or otherwise — the June 26 restriction is the cheapest warning you will get this cycle:
- Audit your default node pool. Is it one
MachineDeploymentin one location with one server type? If so, you are already living the failure movie — just before the scene where the API says no. - Add the fallback before you need it. Duplicate the deployment to a second location, list at least two instance types in the autoscaler's choices, and apply it in staging this week while the locations you want are still in stock.
- Budget headroom, not just list price. Price your fleet with one spare node per location, then stop worrying about the next 10-cent DRAM tick. The scarce resource in 2026 is not the cheaper SKU — it is any SKU that is actually orderable when traffic spikes.
- Prove the second-provider path once. Even if you never send production traffic there, verify that a Scaleway or OVHcloud node can join the same Cluster API management plane and take a non-critical workload. That proof is the asset; the cost is a single test node you can tear down.
The DRAM shock is not done. TrendForce's late-2025 and early-2026 surveys raised Q1 and Q2 contract-price forecasts twice after an already-bad second half of 2025, and suppliers are still guiding constrained output through at least 2027 while HBM crowds classical DRAM. Another round of "price adjustment" emails is more likely than not. But the lesson of June 26 is that the binding constraint for a fleet that provisions its own machines is not always the number on the invoice — sometimes it is the number on the warehouse shelf. Design for that, and the next price email is just a price email again.
Self-hosting your PaaS means the shortage still reaches you — but the fix is your topology, not someone else's ticket queue. Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with a Cluster API fleet you can spread across locations and instance families. Star the repo on GitHub or deploy your first app with a second location in the config from day one.
Sources
- Hetzner Docs — FAQ: temporarily restricting cloud server provisioning at specific locations
- Hetzner Docs — Price Adjustment (general infrastructure notice)
- Data Center Dynamics — Hetzner hikes prices by up to 50% due to drastic component price increases (April 2026)
- TrendForce — HBM vs DDR5 capacity crowding and Q2 2026 DRAM contract price outlook (+58–63% QoQ)
- TrendForce — Memory price outlook for 1Q26 sharply upgraded; QoQ increases to hit record highs
- TrendForce — Higher DDR5 profitability intensifies capacity crowding (December 2025)
- The Register — AWS says server memory shortage is pushing customers to cloud (April 2026, on hyperscaler capacity prioritization)
- Cluster API Provider Hetzner (syself/caph) — HCloudMachineTemplate and MachineDeployment patterns
- karpenter-provider-hetzner — Karpenter cloud provider for Hetzner Cloud
- k0s-hetzner-boilerplate-multizone — Multi-DC HA k0s cluster on Hetzner Cloud