Articles

Kubernetes HPA vs VPA: Autoscaling Explained

Kubernetes HPA scales pod replica count; VPA resizes CPU and memory requests per pod. How each autoscaler works and when to use them together.

Chisato Chisato · · 4 min read
Abstract illustration representing Kubernetes

Kubernetes offers two distinct ways to autoscale a workload: the Horizontal Pod Autoscaler (HPA) changes how many pod replicas are running, and the Vertical Pod Autoscaler (VPA) changes how much CPU and memory each individual pod is allowed to request. They solve different problems, and despite the parallel naming, they’re not interchangeable — understanding which axis you actually need to scale on determines which one fits.

HPA: scaling the number of pods

The HPA watches a metric — by default CPU utilization, but it can also track memory or a custom metric exposed through the metrics API — and adjusts the replicas count on a Deployment or StatefulSet to keep that metric near a target. If average CPU usage across pods climbs above the target utilization, the HPA adds replicas; if it drops well below, it removes them, within configured minimum and maximum bounds.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

This works well for stateless services that can run many identical, independent copies behind a load balancer — a typical web API or worker queue consumer. Each replica handles a slice of the traffic, and adding more replicas linearly adds capacity.

VPA: resizing each pod

The VPA takes the opposite axis: instead of changing how many pods run, it observes actual CPU and memory usage over time and recommends — or, in auto mode, applies — new resource requests and limits for each pod. If a pod’s containers consistently use far less memory than they request, the VPA lowers the request; if they’re regularly close to the limit, it raises it.

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: worker-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: worker
  updatePolicy:
    updateMode: "Auto"

This matters because Kubernetes pods, deployments, and services are scheduled based on their requested resources — a pod requesting more CPU than it needs wastes cluster capacity that could schedule other workloads, while a pod requesting too little risks being throttled or OOM-killed under real load. VPA’s job is finding the right request size, not the right replica count.

Why they don’t simply combine

A workload that’s genuinely stateful, or that can’t be split across many replicas — a single-instance cache, a workload with per-pod local state, or a system with a hard concurrency limit — often benefits more from VPA than HPA, since adding replicas doesn’t help if only one can do useful work. Conversely, a stateless service under variable traffic usually wants HPA, since horizontal scaling is what actually adds throughput.

Running both against the same metric on the same workload is a known anti-pattern: if HPA is scaling replica count based on CPU utilization while VPA is simultaneously resizing each pod’s CPU request, the two can fight each other, since changing a pod’s CPU request changes its measured utilization percentage, which then feeds back into HPA’s scaling decision. The common safe combination is HPA on CPU or a custom metric, and VPA in recommendation-only mode (not auto-applying) on memory, so VPA informs right-sizing without actively fighting HPA’s live scaling loop.

Cluster autoscaling is a third, separate layer

Neither HPA nor VPA adds physical capacity to the cluster — they only change how existing node capacity is allocated among pods. If HPA wants to add replicas but no node has room to schedule them, or VPA wants to raise a pod’s request beyond what any node can fit, those changes stall until capacity exists. A cluster autoscaler, which adds or removes worker nodes based on pending, unschedulable pods, is the layer that actually grows the cluster itself, and it’s typically deployed alongside HPA rather than instead of it.

Choosing between them

HPAVPA
ScalesReplica countPer-pod CPU/memory requests
Best forStateless, horizontally divisible workloadsSingle-instance or hard-to-replicate workloads
Reacts toCPU, memory, or custom metricsObserved usage history
Downtime on changeNone — new replicas just joinAuto mode restarts the pod to apply new limits
Combine safely withVPA in recommendation mode, or on a different metricHPA, if not scaling the same metric

Health checks still matter

Whichever autoscaler you use, newly created or resized pods only receive traffic once they pass their liveness and readiness probes — an HPA that adds replicas faster than they can pass readiness checks doesn’t actually relieve load any faster, it just adds pods that sit unready. Teams running autoscaling at any real scale generally pair it with observability into both the scaling decisions themselves and the underlying metrics driving them, since a misconfigured target utilization is a common, quiet cause of under- or over-provisioned clusters.

The takeaway

HPA scales the number of pod replicas to handle changing load; VPA scales the CPU and memory each pod requests to fit its actual usage. Use HPA for stateless, horizontally divisible services, use VPA for workloads that can’t simply run more copies, and avoid pointing both at the same metric on the same workload, since resizing a pod’s request changes the very utilization number HPA is watching.

Chisato Chisato · · 4 min read

Kubernetes StatefulSets vs Deployments Explained

Deployments manage interchangeable, stateless pods; StatefulSets give each pod a stable identity and storage. When each one actually belongs.

#Kubernetes #DevOps #Cloud
Chisato Chisato · · 5 min read

What Is a Kubernetes Operator?

A Kubernetes operator encodes operational knowledge into software, automating tasks a human admin would otherwise do by hand for a specific application.

#Kubernetes #Cloud #DevOps