KubernetesDevOpsScaling

Kubernetes Autoscaling in 2026: HPA vs VPA vs KEDA — When to Use Each

1 September 2026 · Sphinx-Digital

Kubernetes ships with two native autoscaling mechanisms and one widely-adopted extension. Most teams start with HPA, hit its limits, reach for VPA, find out they conflict, and then wonder why their cluster costs are climbing. The answer is usually KEDA. Here is the full picture.

HPA: Scale Out When Load Spikes

The Horizontal Pod Autoscaler scales the number of pod replicas based on metrics — CPU utilisation by default, but custom metrics from Prometheus or the Metrics Server are equally supported.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300  # 5-min cooldown
      policies:
      - type: Percent
        value: 20
        periodSeconds: 60

The behavior block is critical and often omitted. Without it, HPA will scale down aggressively and cause brief unavailability during traffic dips. The stabilizationWindowSeconds prevents rapid oscillation.

Use HPA when: Your workload scales predictably with CPU or request rate, and adding more pod replicas is the right response to load.

VPA: Right-Size Your Resource Requests

The Vertical Pod Autoscaler adjusts the CPU and memory requests and limits of individual pods. It does not add pods — it makes existing pods use the right amount of resources.

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: api-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  updatePolicy:
    updateMode: "Off"   # Recommendation only; don't auto-apply
  resourcePolicy:
    containerPolicies:
    - containerName: "*"
      minAllowed:
        cpu: 100m
        memory: 128Mi
      maxAllowed:
        cpu: 4
        memory: 4Gi

Start with updateMode: "Off" and read VPA’s recommendations for a week before switching to Auto. VPA in auto mode restarts pods to apply new resource values — this is disruptive and needs testing.

The HPA/VPA conflict: Do not use both on the same deployment with CPU as the target metric. VPA will adjust requests, which changes what HPA sees as “utilisation”, causing them to fight. The safe pattern is VPA for memory and HPA for CPU, or run VPA in Off mode for recommendations only.

KEDA: Scale on Any External Signal

KEDA (Kubernetes Event-Driven Autoscaler) fills the gap HPA leaves open: scaling based on anything that is not a resource metric — a queue length, a Kafka lag, a cron schedule, an HTTP request rate, a Prometheus query.

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-scaledobject
spec:
  scaleTargetRef:
    name: message-worker
  minReplicaCount: 0   # Scale to zero when idle
  maxReplicaCount: 50
  triggers:
  - type: rabbitmq
    metadata:
      host: amqp://rabbitmq.default.svc:5672
      queueName: jobs
      queueLength: "20"   # 1 replica per 20 messages

The minReplicaCount: 0 is KEDA’s killer feature for batch workloads. A deployment that does nothing when the queue is empty should run zero pods, not two. This alone can cut compute costs by 40% for event-driven workloads.

KEDA is a CNCF project at Graduated status (as of early 2026), which means it is production-ready and unlikely to have breaking changes.

Decision Matrix

Signal driving scaleRight tool
CPU utilisationHPA
Memory usageVPA (recommendation mode)
Request rate (HTTP)HPA with custom metrics or KEDA
Queue length (RabbitMQ, Kafka, SQS)KEDA
Cron-based scheduleKEDA
Scale to zeroKEDA
Right-sizing pod resourcesVPA

Training

The Kubernetes training at Sphinx-Digital covers HPA, VPA, and KEDA in a real EKS cluster environment, alongside RBAC, network policies, and production-grade ingress configuration.