Kubernetes 1.37 scales queue consumers to zero replicas with the HPA
On September 2, 2026, Kubernetes 1.37 enabled horizontal scaling to zero replicas by default (Beta) whenever an object or external metric, such as a queue length, allows it. Queue consumers and batch processors can release reserved CPU and GPU while idle, provided they accept the cold-start latency.
Kubernetes 1.16. HorizontalPodAutoscaler scaling to zero enters Alpha. September 2, 2026. The feature graduates to Beta and turns on by default in Kubernetes 1.37, with the ScaledToZero condition to tell an automatic scale-down from a manual pause. 2026. The effort, owned by SIG Autoscaling, took seven years to mature. Why it matters: for the first time, dropping a Deployment to zero replicas when its queue is empty is part of core Kubernetes, with no external add-on.
Why scaling to zero changed the metric
The HPA typically scales on CPU or memory. The trap is mechanical: both metrics come from running Pods. Once the replica count reaches zero, there is no Pod left to measure, and no signal to tell the HPA to scale back up. Reaching zero therefore required an add-on like KEDA, an external component, or enabling an Alpha feature gate.
Object and external metrics do not have that limitation. A queue length exists independently of the workers that consume it: the HPA can keep reading it while no worker runs. That change of metric is what makes native scale-to-zero possible. The trade-off is cold start: the HPA must observe the metric, schedule a Pod and start the application before the work is processed.
An HPA driven by the queue
The canonical example is a queue consumer whose lag is tracked by Prometheus. The queue_consumer_lag series is exposed to the HPA through a metrics adapter — the reference implementation is the Prometheus Adapter, which publishes the series through the external metrics API:
externalRules:
- seriesQuery: '{__name__="queue_consumer_lag",name!=""}'
metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (name)
resources:
overrides:
namespace:
resource: namespace Before creating the HPA, verify that Kubernetes can read the metric — otherwise the HPA can never climb back from zero:
kubectl get --raw \
'/apis/external.metrics.k8s.io/v1beta1/namespaces/default/queue_consumer_lag?labelSelector=name%3Dworker_tasks' The HPA below targets a queue-worker Deployment, allows between zero and ten replicas and 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" With an empty queue, the HPA reduces the Deployment to zero replicas; when tasks arrive, the external metric stays available and the HPA recomputes a replica count capped by maxReplicas. The default five-minute downscale stabilization window stops a brief drop in queue length from removing all workers at once: you can tune it through spec.behavior.scaleDown.
The ScaledToZero condition, or how to tell pause from stop
Setting a Deployment to zero creates an ambiguity: zero replicas can mean the HPA scaled it down, or that an operator paused it manually. Historically, setting a Deployment to zero by hand froze autoscaling.
The controller resolves this with a ScaledToZero status condition. When the HPA moves a workload from one or more replicas to zero, it records ScaledToZero=True: later reconciliation knows the controller owns that zero state and keeps evaluating the metrics. After scaling back up, the condition flips to ScaledToZero=False with the reason NotScaledToZero. A workload at zero without ScaledToZero=True stays considered paused — the HPA will not wake it, as before.
kubectl describe hpa queue-worker If the adapter cannot return the metric, the HPA reports ScalingActive=False with a reason like FailedGetExternalMetric. Restore the metric or scale the workload up manually to recover capacity. This is the main watchpoint: an HPA at zero depends entirely on its metric being available.
What not to do
The feature has sharp limits, and ignoring them is costly. Kubernetes Services do not buffer requests while no Pod is ready: an HTTP or request-driven workload scaled to zero will fail requests rather than wait. Those cases need a separate buffering layer — precisely the niche of KEDA, which scales on queue depth or a Kafka topic and knows how to expose a scaled object.
Two operational constraints complete the picture. minReplicas: 0 requires at least one object or external metric: the API server rejects an HPA that only contains resource metrics such as CPU or memory. And during a version-skewed upgrade, wait until both kube-apiserver and kube-controller-manager support the feature before creating zero-scaled HPAs: a controller with the feature gate disabled treats replicas: 0 as a manual pause and may leave a workload stuck at zero.
The good news is that the failure modes are explicit. ScaledToZero, ScalingActive and FailedGetExternalMetric are observable states, not silent guesses: a team that watches its HPA conditions will see a broken metric pipeline before it becomes a silent outage.
Native HPA or KEDA: the real trade-off
The question is not “which is better” but “which semantics your workload expects”. The native zero-scaled HPA fits the simple case: a queue consumer whose work can wait in a durable queue, and whose Pods reserve expensive resources — dedicated CPU, GPU. The savings peak there: a GPU worker pool running idle burns money continuously.
KEDA remains ahead whenever the workload is event-driven in the broad sense: Kafka, RabbitMQ, triggered functions, or any source that needs a specialized scaler and fine-grained buffering. The HPA’s progress does not replace KEDA; it shrinks the need for it in the most common case.
The math that makes scale-to-zero pay
The saving is measured in reserved resources, not replicas. A pool of ten GPU workers idling at zero load reserves ten GPUs around the clock — a cost that keeps running even when no task is queued. Scaling to zero does not remove the cost of the underlying infrastructure, but it frees the nodes for other workloads: in a cluster where GPUs are scarce, a stopped worker is a GPU handed back for training or a batch.
The gain only holds if the work can wait. A durable queue — Redis, RabbitMQ, Kafka or a managed cloud queue — is the entry condition: if the work must be processed immediately, the cold-start latency becomes a product defect, not an infrastructure compromise.
The concrete tipping point sits on latency. The HPA observes the metric on a regular interval: between a task arriving and a replica scaling back up, tens of seconds can pass, more with the cold start. KEDA, by subscribing directly to the event source, shrinks that delay. For a nightly batch or a consumer that tolerates thirty seconds of lag, the difference is negligible; for a low-latency queue, it is not.
Finally, keep the hidden coupling in mind: a zero-scaled HPA depends entirely on its metric being available. If Prometheus or the adapter goes down, the HPA cannot climb back up — a monitoring outage becomes a worker-pool outage. That is the price to fold into the saving calculation, especially since scaling to zero targets exactly the quiet periods.
Verdict
If you run a queue consumer whose Pods reserve expensive resources and whose work can wait in a durable queue, move to Kubernetes 1.37 and declare minReplicas: 0 with an external metric: you cut idle-period cost with no add-on.
If your workload is HTTP or request-driven, do not scale to zero with the HPA alone: keep a buffering layer, or stay on KEDA to absorb requests during startup.
In every case, exercise the climb back from zero in real conditions before enabling it in production, and watch ScalingActive: an HPA that can no longer read its metric is a workload that will not restart.
References
- Kubernetes Blog — Kubernetes v1.37: Scale Workloads to Zero with HorizontalPodAutoscaler, September 2, 2026
- Kubernetes Docs — Horizontal Pod Autoscaling: scaling to and from zero
- KEP-2021 — HPA supports scaling to and from zero pods for object and external metrics
- Prometheus Adapter — External metrics documentation