The useful answer to HPA vs VPA vs KEDA begins with the bottleneck. Horizontal Pod Autoscaler changes replica count, Vertical Pod Autoscaler changes CPU and memory requests, and KEDA connects event sources to activation and horizontal scaling. None can repair an application that does not become faster when its controlled variable changes. Before installing another controller, identify the queue, resource, concurrency limit, dependency, or scheduling constraint that prevents the service-level objective from being met.
Autoscaling is feedback control. The signal arrives late, the new capacity takes time to become useful, and the demand may change again before the controller reacts. A stable design needs an observable demand measure, a target with clear units, enough headroom for actuation delay, and scale-down rules that do not destroy useful work. The Kubernetes autoscaling overview distinguishes horizontal and vertical mechanisms; production design must additionally account for how those loops interact with node provisioning and application backpressure.
Diagnose the bottleneck through six scaling questions
Trace one unit of work from arrival to completion. Record arrival rate, queue age, active concurrency, service time, CPU throttling, memory working set, dependency latency, retry volume, pod startup, readiness, and node provisioning delay. Run a controlled load step and ask what saturates first. CPU utilization is meaningful when throughput rises with CPU and replicas are comparable. Queue depth is meaningful when each replica drains work at a measurable rate. Memory pressure may require a larger pod, but a leak requires a code fix rather than a larger limit.
| Observed constraint | Best starting mechanism | Why | Main caveat |
|---|---|---|---|
| Replicas can process independent requests | HPA | Changes parallel serving capacity from resource or custom metrics | Startup and metric lag need headroom |
| Pod requests are persistently wrong | VPA recommendations, then updates | Rightsizes CPU and memory reservations | Updates may resize or recreate pods |
| External backlog or scheduled demand | KEDA ScaledObject or ScaledJob | Activates from event-source semantics and can reach zero | Scaler availability and cold starts matter |
| Batch admission exceeds shared quota | Queueing system before pod scaling | Controls which work enters the cluster | Replica scaling alone cannot create quota |
| Database or license concurrency is fixed | Backpressure plus bounded replicas | Protects the real dependency | More pods can worsen overload |
Use HPA when replicas change useful capacity
HPA targets a scalable workload and periodically computes a desired replica count. With autoscaling/v2, it can use resource, pod, object, and external metrics. The HPA documentation explains readiness handling, missing metrics, multiple metrics, tolerances, and configurable behavior. Use a per-pod utilization target only when requests are credible; CPU utilization is measured relative to requests, so under-requested containers appear busy and over-requested ones appear idle even at the same absolute CPU use.
Set minReplicas to cover ordinary availability and cold-start tolerance, and maxReplicas from downstream capacity, quota, and cost rather than optimism. Configure scale-up policies for the fastest safe change and a scale-down stabilization window long enough to absorb request variance. Startup probes and readiness probes should prevent initialization spikes and non-serving pods from distorting the signal. When several metrics are present, HPA uses the largest recommended replica count; every metric therefore needs a defined failure behavior and owner.
Use VPA to correct the pod resource shape
VPA observes use and recommends requests. Begin in Off mode to inspect lower bound, target, and upper bound without changing workloads. Compare recommendations across business cycles, deployments, and failure conditions; a recommendation trained on quiet traffic should not become a production limit. The upstream VPA quick start documents explicit Recreate, Initial, Off, and InPlaceOrRecreate modes, with the last using in-place updates when possible and falling back to recreation.
Do not let VPA and CPU- or memory-utilization HPA independently control requests and replicas without modeling the coupling. If VPA raises CPU requests, reported utilization can fall and HPA can reduce replicas; VPA may then observe a different load per pod and revise requests again. Safer patterns include VPA recommendations with manual review, VPA plus HPA on an external or absolute workload metric, or a deliberately tested multidimensional design. Preserve limits separately when they express a safety boundary; recommendations are not a license to remove resource governance.
Use KEDA when event semantics should activate capacity
KEDA polls an event source, exposes metrics, and manages an HPA for a ScaledObject. Its scaling model separates activation from zero to one from HPA-driven scaling above one. This is valuable for queues, streams, scheduled workloads, and external systems where CPU is a trailing signal. Choose a trigger that represents drainable work: queue age may protect latency better than depth when message sizes vary, while lag needs partition and consumer semantics understood before it becomes a target.
Scale-to-zero trades idle cost for activation latency and operational dependence on the scaler, metric adapter, event source, image pull, scheduling, and application startup. Set polling, activation threshold, cooldown, fallback, and replica bounds from an explicit latency budget. The KEDA FAQ warns against attaching a separate HPA and ScaledObject to the same target because KEDA already manages an HPA. Consolidate triggers in one ScaledObject and test metric failure, authentication expiry, and an unreachable broker.
| Loop pair | Possible conflict | Design guardrail | Evidence to watch |
|---|---|---|---|
| HPA and VPA | Request changes alter utilization and replica advice | Use external HPA metric or recommendation-only VPA | Requests, utilization and replicas on one timeline |
| KEDA and manual HPA | Two owners write the same scale target | One ScaledObject owns horizontal behavior | HPA owner references and reconciliation events |
| Pod and node autoscaling | Pods scale before nodes become ready | Reserve headroom or include provisioning delay | Pending reasons and time to Ready |
| Scale-down and long work | Termination discards in-flight processing | Checkpoint, graceful shutdown or ScaledJob | Completion, retry and duplicate rates |
| Multiple HPA metrics | Noisy metric dominates recommendation | Validate units, targets and failure policy | Desired replicas by metric |
Test autoscaling as a complete system
Create tests for a step increase, sustained plateau, sharp drop, event-source outage, missing metrics, pod crash, unavailable node capacity, and downstream throttling. Capture time from demand to metric, metric to desired replicas, desired replicas to scheduled pods, scheduled to Ready, and Ready to useful throughput. Repeat with a fresh image and scaled-down node pool. A controller can react correctly while the service still misses its objective because image pulls or initialization dominate the response.
Promote autoscaling in advisory or narrow-bound mode first. Compare expected and actual decisions, then expand bounds. Alert on controller inability to fetch metrics, prolonged maximum replicas, pending pods, frequent direction changes, scale-to-zero activation failures, and VPA recommendations outside policy. Review targets after code, instance type, dependency, traffic mix, or startup changes. An autoscaler configuration is a model of the workload, and models expire.
Derive targets from throughput and delay budgets
Convert service objectives into a first target rather than selecting a round utilization number. For a queue consumer, measure sustainable items per second per ready replica at the intended CPU and memory. Required replicas are driven by arrival rate plus the rate needed to clear acceptable backlog within its age objective, bounded by partition count and downstream concurrency. For request serving, combine peak arrival, service time, permitted concurrency, and startup delay. Leave error and failover headroom; a target at laboratory saturation guarantees that real variance appears as latency.
Validate the target across traffic mixes. CPU may correlate with throughput for compute-heavy requests but not for cached or dependency-bound ones. Queue depth may treat a one-second item like a ten-minute item. Use age, weighted backlog, or separate workload classes when one aggregate loses meaning. Record units and aggregation explicitly, including whether a metric is per pod, total, average, rate, or gauge. Many apparent controller faults are actually a target paired with the wrong metric type.
Capacity economics provide the final bound. Calculate the maximum replicas that downstream pools, licenses, provider quotas, and the node fleet can support, then load-test that ceiling. If the service objective demands more, redesign before raising maxReplicas. Autoscaling should expose an impossible capacity plan early. Keep a manual emergency floor and ceiling procedure with expiry, because incidents sometimes require stabilizing one loop while engineers repair its signal.
Key takeaways
- Name the saturated resource or queue before choosing a controller.
- Use HPA when additional replicas create useful parallel capacity.
- Use VPA to correct CPU and memory requests, with explicit update mode and disruption policy.
- Use KEDA for event-driven activation and horizontal scaling, including deliberate cold-start design.
- Give each scale target one horizontal owner and test the full demand-to-throughput delay.
Frequently asked questions
Can HPA and VPA be combined?
Yes, but avoid unmanaged coupling when both depend on CPU or memory utilization. VPA recommendations plus HPA on an external demand metric is easier to reason about than two loops changing the denominator and replica count.
Does KEDA replace HPA?
KEDA extends horizontal scaling with event sources and activation. For ScaledObjects it creates and manages an HPA above the activation range, so a second HPA should not control the same workload.
Will VPA solve a memory leak?
No. It may change the request or delay failure, but an unbounded working set remains an application defect. Keep limits, alerts, and remediation ownership in place.
Conclusion
Autoscaling succeeds when it controls the variable that relieves the actual constraint. Diagnose the work path, select HPA, VPA, KEDA, or queueing for that constraint, and then engineer the delays and interactions around it. The right comparison is not which controller has more features; it is which feedback loop produces safe, timely capacity without fighting another owner.