Back to Scaling, Load Balancing & Performance
Q1Question 1 of 20

The difference between Kubernetes HPA, VPA, and Cluster Autoscaler, and when to use KEDA

Key Concepts
  • HPA changes the number of pod replicas based on CPU, memory, or custom metrics: scaling out and in.
  • VPA adjusts CPU and memory requests of individual pods by recreating them: scaling the size up and down.
  • Cluster Autoscaler adds or removes whole nodes when pods cannot be scheduled or nodes sit idle.
  • HPA and VPA must NOT target the same metric or they oscillate; let HPA own CPU and VPA own memory.
  • KEDA scales on event signals like Kafka consumer-group lag or queue depth instead of CPU.
  • KEDA can scale to zero when there is no work and scale up instantly when messages arrive.
  • These tools are layered: HPA/KEDA decide how many pods, VPA decides how big, Cluster Autoscaler decides how many nodes.

Definition

HPA adds more pods, VPA makes each pod bigger, Cluster Autoscaler adds more nodes, and KEDA scales on event signals like queue depth instead of CPU: different layers for different problems.
  • HPA (Horizontal Pod Autoscaler) – changes the number of pod replicas based on observed load like CPU or custom metrics, scaling out and in.
  • VPA (Vertical Pod Autoscaler) – adjusts the CPU and memory requests of individual pods by recreating them, scaling the size up and down.
  • Cluster Autoscaler – adds or removes whole nodes from the cluster when pods cannot be scheduled or nodes sit idle.
  • KEDA – an event-driven add-on that lets the HPA scale on external signals such as queue depth or Kafka lag rather than CPU.
  • Layering – HPA/KEDA decide how many pods, VPA decides how big each pod is, and the Cluster Autoscaler decides how many machines exist to hold them.

Imagine the National Bank of India's processing floor. HPA is the policy of opening more identical counters when the queue grows and closing them when it shrinks. VPA is the policy of giving each individual clerk a bigger desk because the work needs more space than first allotted. The Cluster Autoscaler is the facilities team that leases another floor when there is no room for new counters. KEDA is the special rule for the back office: instead of watching how hard the clerks are sweating, it watches the height of the pending-forms pile and pulls in workers the instant the pile grows, even from zero.

Understanding the Concepts

What is the Horizontal Pod Autoscaler (HPA)?

The HPA operates on replica count. It watches a metric, classically average CPU utilization, and compares it to a target. If the current value exceeds the target, it scales out; if it falls below, it scales in.

YAML
# hpa.yaml for National Bank of India's Payment Service
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: payment-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: payment-service
  minReplicas: 2
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60
TEXT
Expected behavior:
Pods running at 90% CPU -> HPA scales to more replicas until avg drops to 60%
Pods running at 30% CPU -> HPA scales in to minReplicas (2)
Bound: never fewer than 2, never more than 20

What is the Vertical Pod Autoscaler (VPA)?

The VPA adjusts the CPU and memory requests of a single pod. It observes actual usage over time and recommends or automatically sets more appropriate requests.

YAML
# vpa.yaml for batch settlement service
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: settlement-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: settlement-service
  updatePolicy:
    updateMode: "Auto"  # Recreates pods to apply new sizes
  resourcePolicy:
    containerPolicies:
      - containerName: settlement
        minAllowed:
          cpu: "250m"
          memory: "256Mi"
        maxAllowed:
          cpu: "2"
          memory: "4Gi"
TEXT
Expected behavior:
Settlement pod requests 500m CPU but only uses 200m -> VPA recommends 250m
Settlement pod requests 256Mi memory but uses 1Gi -> VPA recreates with 1Gi
Catch: pod is RESTARTED to apply new sizes (disruptive for latency-sensitive)

What is the Cluster Autoscaler?

The Cluster Autoscaler adds or removes whole nodes. When pods are pending because no node has room, it provisions more nodes. When nodes sit idle, it removes them.

TEXT
Scenario at National Bank of India during festival season:

1. HPA wants 30 payment-service replicas
2. Current 5 nodes can only fit 20 pods
3. 10 pods are PENDING (unschedulable)
4. Cluster Autoscaler provisions 2 more nodes
5. Pending pods get scheduled on new nodes
6. After festival: traffic drops, HPA scales to 5 pods
7. 4 nodes are underutilized
8. Cluster Autoscaler removes 2 nodes, reschedules remaining pods

Can HPA and VPA be used together safely?

You must not have both HPA and VPA act on the same resource metric. If both target CPU, they fight: HPA adds replicas while VPA enlarges each pod, and the two oscillate.

JAVA
package com.bank.scaling;

/**
 * WRONG: Both HPA and VPA target CPU.
 * HPA sees high CPU -> adds replicas
 * VPA sees high CPU -> enlarges pods (restarts them)
 * Both fight each other, pods restart constantly.
 *
 * CORRECT: Separate their concerns.
 * HPA targets CPU (or custom request-rate metric)
 * VPA targets memory (in recommendation-only mode)
 * No overlap, no oscillation.
 */
public class AutoscalerDecisionGuide {
    // This is a documentation class showing the safe pattern.
}
TEXT
Safe pattern:
  HPA -> scales on CPU or request-rate (horizontal)
  VPA -> manages memory in recommendation-only mode (vertical)
  Never point both at CPU.

Unsafe pattern:
  HPA -> CPU target 60%
  VPA -> CPU target auto
  Result: oscillation, constant pod restarts, thrashing

When do you use KEDA?

KEDA addresses workloads where CPU is a poor proxy for how much work is waiting. A Kafka consumer can sit at low CPU while a huge backlog builds.

YAML
# keda-scaledobject.yaml for settlement worker
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: settlement-worker-scaler
spec:
  scaleTargetRef:
    name: settlement-worker
  pollingInterval: 10
  cooldownPeriod: 300
  minReplicaCount: 0   # Scale to zero when idle
  maxReplicaCount: 50
  triggers:
    - type: kafka
      metadata:
        bootstrapServers: kafka:9092
        consumerGroup: settlement-group
        topic: settlement-events
        lagThreshold: "100"
TEXT
Expected behavior:
No messages in settlement-events -> 0 pods (cost savings)
500 messages arrive at market close -> KEDA scales to 5 pods instantly
Backlog drained -> cool down -> scale back to 0

CPU-based HPA would not react because idle consumer has low CPU.
KEDA watches the actual queue depth.

How is HPA different from VPA and KEDA? (comparison table)

| Aspect | HPA | VPA | KEDA |
|---|---|---|---|
| What it changes | Number of pods | Size of each pod | Number of pods (event-driven) |
| Scaling axis | Horizontal (out/in) | Vertical (up/down) | Horizontal (out/in) |
| Default metric | CPU, memory | CPU, memory usage | Queue depth, Kafka lag |
| Scale to zero | No (minReplicas >= 1) | No | Yes |
| Pod disruption | None (adds/removes pods) | Restarts pods | None (adds/removes pods) |
| Best for | Stateless request-serving | Batch, background jobs | Bursty, queue-based workloads |

How do these tools layer together?

These tools are complementary, not competing. HPA and KEDA decide how many pods, VPA decides how big each pod is, and the Cluster Autoscaler decides how many machines exist to hold them.

DIAGRAM
  ┌─────────────────────────────────────────────┐
  │        Application Layer (Pods)              │
  │                                              │
  │  HPA: "I need 10 payment-service pods"       │
  │  KEDA: "I need 5 settlement-worker pods"     │
  │  VPA: "Each pod needs 512Mi memory"          │
  └──────────────────────┬──────────────────────┘
                         │
  ┌──────────────────────┴──────────────────────┐
  │        Infrastructure Layer (Nodes)          │
  │                                              │
  │  Cluster Autoscaler: "I need 7 nodes to     │
  │  fit all 15 pods at their requested sizes"   │
  └─────────────────────────────────────────────┘

What should a senior engineer know?

Aggregate size is a direct throughput lever. Use HPA for synchronous request-serving services, KEDA for bursty queue-based workloads, VPA for right-sizing background jobs, and the Cluster Autoscaler to ensure nodes exist for all of them. Never point HPA and VPA at the same metric.

Visual Overview

DIAGRAM
  Kubernetes Autoscaling Layers:

  ┌──────────────────────────────────────────┐
  │               HPA / KEDA                  │
  │  "How many pods?"                         │
  │  HPA: CPU/memory/custom metrics           │
  │  KEDA: Kafka lag, queue depth, events     │
  └────────────────────┬─────────────────────┘
                       │
  ┌────────────────────┴─────────────────────┐
  │                 VPA                       │
  │  "How big is each pod?"                   │
  │  Adjusts CPU/memory requests              │
  │  Restarts pods to apply                   │
  └────────────────────┬─────────────────────┘
                       │
  ┌────────────────────┴─────────────────────┐
  │         CLUSTER AUTOSCALER                │
  │  "How many nodes?"                        │
  │  Adds nodes when pods are pending         │
  │  Removes idle nodes to save cost          │
  └──────────────────────────────────────────┘

Key Takeaway

These are three complementary Kubernetes autoscalers that operate on completely different axes, plus an event-driven add-on. The Horizontal Pod Autoscaler changes the number of pod replicas based on a load metric like CPU. The Vertical Pod Autoscaler adjusts the CPU and memory requests of each individual pod. The Cluster Autoscaler adds or removes whole nodes when pods cannot be scheduled or nodes sit idle.

On the key question of whether HPA and VPA can be used together, the answer is yes but only if they do not act on the same resource metric. If both target CPU, they fight: the HPA tries to fix high CPU by adding replicas while the VPA tries to fix the same high CPU by enlarging each pod, and the two oscillate. The safe pattern is to let the HPA own CPU and let the VPA manage memory in recommendation-only mode.

KEDA is what you reach for when CPU is a poor proxy for how much work is waiting. At National Bank of India, the settlement worker sits idle most of the day and is flooded at market close. Switching from CPU-based scaling to KEDA on queue depth means it sits at zero pods when quiet and shoots up instantly when the backlog appears.

Remember one sentence: HPA and KEDA decide how many pods, VPA decides how big each pod is, Cluster Autoscaler decides how many nodes exist to hold them, and never point HPA and VPA at the same metric.

---

Share
Use ← → arrow keys to navigate