Every git-push PaaS pays a tax it never itemizes: the always-on replica. Each idle tenant service holds one pod — reserved CPU and memory, doing nothing — just so the next request doesn't land on an empty Service. Kubernetes v1.37 "Garhwal," shipped August 26, 2026, with a follow-up announcement on September 2, finally removes the reason for that tax: HorizontalPodAutoscaler scale-to-zero graduated to beta and is now enabled by default. A Deployment-backed worker can drop its last replica when idle and come back when demand returns, with no Knative or KEDA bolted on.
The economics in one paragraph: a bursty tenant service that sits idle two-thirds of the day spends roughly two-thirds of its reserved compute doing nothing. At an illustrative $3/month in reserved capacity per standing replica (one-eighth of a $24/month 4-vCPU/8-GB node), a platform with 100 such services burns about $300/month on replicas that exist only to avoid a cold start — and native scale-to-zero reclaims on the order of $200 of it as bin-packable headroom.
The price is cold-start latency on wake-up plus one architectural gap v1.37 deliberately leaves open: Kubernetes Services still don't buffer requests, so HTTP workloads need a scale-from-zero activator the platform provides itself. That tradeoff — zero standing cost for workers, an activator still required for request-driven traffic — is the whole story of this beta.
What actually shipped in v1.37
The feature is minReplicas: 0 on a standard HPA, and the mechanics matter because they define exactly which workloads qualify. An HPA that sets minReplicas: 0 must scale on at least one object metric or external metric — the API server rejects a scale-to-zero HPA driven only by CPU or memory. The reason is physical: resource metrics come from running pods, so at zero replicas there is nothing left to measure and no signal that could ever scale the workload back up. A queue length or a Prometheus-exposed business metric exists independently of the workers consuming it, so the HPA can keep reading it at zero and wake the Deployment when it moves.
The reference setup from the September 2 announcement (Johannes Würbach) is a queue consumer: Prometheus collects queue_consumer_lag, the Prometheus Adapter exposes it through the External Metrics API, and the HPA requests one replica per 30 queued tasks:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: queue-worker
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: queue-worker
minReplicas: 0
maxReplicas: 10
metrics:
- type: External
external:
metric:
name: queue_consumer_lag
selector:
matchLabels:
name: worker_tasks
target:
type: Value
value: "30"Three operational details come with the beta:
- Zero vs. paused. The controller distinguishes "HPA scaled this to zero" from "an operator paused this" with a
ScaledToZerostatus condition (introduced in v1.36): only a workload carryingScaledToZero=Truegets woken automatically, while a manually zeroed Deployment stays paused. - Stabilization still applies. Normal HPA behavior is unchanged, including the default five-minute downscale stabilization window — a brief dip in queue length won't immediately delete every worker.
- Both components must agree. The
HPAScaleToZerofeature gate must be on in kube-apiserver and kube-controller-manager alike; during a version-skewed control-plane upgrade, a controller manager without the feature treatsreplicas: 0as a manual pause and may leave a workload stranded at zero. Before any rollback, the documented recovery is to set affected HPAs back tominReplicas: 1or higher and manually scale zeroed workloads up.
The history is worth noting: the first alpha of HPA scale-to-zero shipped back in v1.16. It took until v1.36's condition-based implementation and v1.37's integration and end-to-end coverage for the project to enable it by default — a decade-long caution that tells you this beta deserves a staging rollout, not a flag-day.
The idle-service math
Scale-to-zero only pays when a service is actually idle, so the honest way to evaluate it is across idle fractions, not one convenient example. Take the same illustrative standing replica at $3/month in reserved capacity and a bursty tenant service — a staging app, a cron-driven worker, an internal tool used during business hours:
| Idle fraction (example pattern) | Standing waste, always-on | Reclaimed with scale-to-zero |
|---|---|---|
| 25% (busy service, brief lulls) | ~$0.75/mo | ~$0.75/mo — likely not worth the cold starts |
| 50% (12h active / 12h idle) | ~$1.50/mo | ~$1.50/mo per service |
| 67% (8h active / 16h idle) | ~$2.00/mo | ~$2.00/mo per service |
| 90% (nights-and-weekends pattern) | ~$2.70/mo | ~$2.70/mo per service |
Per service these are single dollars — the payback is at fleet scale. One hundred bursty services at 67% idle waste roughly $200/month in reserved-but-idle capacity that scale-to-zero converts into headroom for other tenants on the same nodes. On owned hardware, where the bill is fixed and the constraint is how many tenants fit per machine, that headroom is the margin between buying another server this quarter or next. The official announcement makes the same point at the top end: savings are largest when each pod reserves expensive resources such as dedicated CPUs or GPUs.
Industry data says the idle share dwarfs any single feature's savings, which is exactly why the default matters. Datadog's State of Cloud Costs report attributes 83% of container costs to idle resources; CAST AI's 2026 optimization report found average utilization of just 8% for CPU, 20% for memory, and 5% for GPU across tens of thousands of clusters; Komodor's analysis puts 82% of Kubernetes workloads in the overprovisioned camp. Scale-to-zero doesn't fix overprovisioned requests — but it deletes the purest form of waste, the replica that exists only to hold a place.
Now the other column of the ledger: cold-start latency is the explicit tradeoff. Waking a workload means the HPA must observe the metric, schedule a pod, pull the image if it isn't cached, and start the application — seconds at best, tens of seconds for heavy runtimes. That is why the announcement frames the feature around work that can wait in a durable queue: a queue consumer with a five-minute stabilization window never notices a thirty-second cold start, while a latency-sensitive HTTP endpoint absolutely does. And there is a new hard dependency: if the metrics adapter can't serve the configured metric, the HPA reports ScalingActive=False and the workload sits at zero until the pipeline is restored or someone scales it manually. The metric pipeline is now on the critical path for capacity, not just observability.
What v1.37 replaces — and the piece it doesn't
For metric-driven workloads, the native primitive now covers ground that previously required an add-on. The established division of labor, described in João Valentim's widely shared May 2026 account of scaling to zero across thousands of apps, was that KEDA drives the 0-to-1 transition (a ScaledObject with minReplicaCount: 0 performs activation itself) while HPA handles 1-to-N. A v1.37 HPA with minReplicas: 0 absorbs the first half of that split for any workload whose wake-up signal is already an object or external metric — queue consumers, batch processors, scheduled workers. If KEDA's only job on your platform was bridging that 0-to-1 gap for metric-driven webhooks, the beta lets you delete a moving part: one fewer CRD, one fewer controller to upgrade, and autoscaling expressed entirely in core autoscaling/v2 objects your existing tooling already understands.
What v1.37 does not replace is the request path. The announcement states the gap plainly: Kubernetes Services do not buffer requests while no pods are ready, so HTTP and other request-driven workloads need a separate buffering layer. Scaling an HTTP Deployment to zero with HPA alone means the request that arrives during the cold start has nowhere to go — no queue to wait in, no pod to serve it. Something must sit in the request path, hold the inbound request, trigger the scale-up, and forward the request once a pod is ready.
That something is what Knative already bundles. In Knative Serving's scale-from-zero flow, the activator intercepts traffic for a zeroed revision, buffers the request, reports demand to the autoscaler (KPA, scaling on request concurrency), and forwards the buffered request once pods are ready — with a queue-proxy sidecar in every pod measuring what the autoscaler needs. The first request pays the cold start, but it gets served rather than dropped. Native HPA-to-zero has no equivalent component: it can scale the Deployment, but it cannot catch the request that should have caused the scaling. For HTTP services, a git-push PaaS adopting this beta must still provide its own activator — Knative's, a gateway that holds and retries, or a purpose-built buffering proxy — or restrict scale-to-zero to workloads whose callers tolerate failure and retry.
So the migration map splits cleanly by workload shape. Queue workers, batch jobs, cron-driven processors, and GPU inference workers behind a queue: adopt the native primitive and retire the KEDA ScaledObjects or hand-rolled idle-reaper cronjobs that did the 0-to-1 job. HTTP services with human-facing latency budgets: keep Knative or your activator, and treat HPA-to-zero as the scaling engine underneath it rather than a replacement for it. The beta shrinks the add-on footprint; it doesn't eliminate the need to think about the request path.
Adoption playbook for a git-push PaaS
A sensible rollout order falls out of the workload split above. Start with the workloads where the beta is strictly better than the status quo: queue consumers and batch processors already exposing a lag or depth metric. The prerequisites are mechanical:
- A metrics adapter serving the signal through the External Metrics API — verify with
kubectl get --rawon theexternal.metrics.k8s.ioendpoint before creating the HPA. - An HPA with
minReplicas: 0and a sanemaxReplicascap. - The Deployment starting from at least one replica, so the HPA owns the first scale-down and records the
ScaledToZerocondition.
Tune the behavior windows second. The five-minute default downscale stabilization is a reasonable starting point, but bursty tenant traffic may want a longer idle hold to avoid flapping between zero and one on every stray request — each flap is a cold start billed in latency. Pair the window with maxReplicas caps sized to the node's actual headroom: a fleet that reclaimed its idle capacity by bin-packing tighter has less slack for ten workers waking at once, and the thundering-herd case (deploy event, cron stampede) deserves a load test before it deserves production traffic.
Guard the upgrade path third. Don't create minReplicas: 0 HPAs until both apiserver and controller-manager run v1.37 with the gate enabled; a skewed controller can strand workloads at zero by misreading autoscaled zero as a manual pause. Keep the rollback runbook next to the rollout: flip affected HPAs to minReplicas: 1, scale zeroed workloads up, then disable or downgrade. And put the metrics pipeline under the same monitoring as the control plane itself — an adapter outage is now a capacity outage for every zeroed workload, announced only by ScalingActive=False.
Finally, decide the HTTP story explicitly rather than letting it happen by accident. Either keep request-driven services on Knative (or your existing activator) with HPA-to-zero as the engine, or build the buffering layer before enabling zero for anything user-facing. The failure mode of skipping this decision is the worst of both worlds: services that scale to zero correctly and then drop the exact requests that should have woken them.
The always-on replica had a good run
HPA scale-to-zero reaching beta, enabled by default, closes a loop that has been open since the v1.16 alpha: the core autoscaler can now express "this workload costs nothing when idle" without an add-on translating for it. For a self-hosted PaaS, where every reclaimed replica is headroom on hardware you already own rather than a line item on a cloud bill, that primitive lands directly on the margin between comfortable bin-packing and the next server purchase. The beta label still means something — the project is explicitly gathering operational feedback before considering GA — so the right posture is staged adoption starting with queue-driven workers, not a fleet-wide flag-day.
The open question for GA is whether the request-path gap narrows. As long as Services can't buffer, HTTP scale-to-zero remains a two-component solution: HPA for the scaling decision, an activator for the request that triggers it. Whoever standardizes that second half — a Gateway API-native buffering story, a slimmed-down activator pattern, or Knative continuing to own it — decides how far "zero standing cost" extends beyond the queue. Until then, the playbook is clear: let the native primitive zero your workers, and budget the activator for everything a human is waiting on.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



