
August 17, 2026
11 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
Configuring Kubernetes Autoscaling: HPA, VPA and Cluster Autoscaler correctly is the difference between a resilient platform and an unpredictable billing nightmare. While many developers treat these as interchangeable scaling tools, they solve fundamentally different problems at distinct layers of the infrastructure stack. Misunderstanding their boundaries leads to resource contention, failed deployments, or massive over-provisioning that drains budgets faster than traffic spikes can justify.
For teams managing production workloads, especially those transitioning from traditional VPS setups or exploring cloud migration strategies, understanding this separation of concerns is non-negotiable. You cannot simply enable all three and expect harmony; without explicit coordination policies, VPA will fight HPA, and both will trigger erratic Cluster Autoscaler behaviour. This guide breaks down exactly how each component functions in 2026, where they overlap, and how to configure them safely for real-world applications ranging from Laravel APIs to high-throughput data processors.
How does Horizontal Pod Autoscaler (HPA) handle traffic-driven scaling?
The Horizontal Pod Autoscaler is the most mature and widely used component of the Kubernetes autoscaling triad. Its job is singular: adjust the number of pod replicas in a Deployment, StatefulSet, or ReplicaSet based on observed metrics. In practice, HPA excels at handling predictable and unpredictable traffic patterns for stateless services where adding more identical instances linearly increases throughput.
Core mechanics and metric sources
HPA operates on a control loop that queries the Metrics API every 15 seconds by default. It supports two primary metric types:
- Resource Metrics: CPU and memory utilization relative to the pod's requested resources. This requires the Metrics Server to be installed and healthy.
- Custom/External Metrics: Application-specific signals like queue depth, HTTP requests per second, or database connection pool saturation. These require the Custom Metrics API or External Metrics API adapter (e.g., Prometheus Adapter).
A common mistake I see on client projects is setting HPA targets based on limits rather than requests. HPA calculates utilization as currentValue / request. If your pod requests 250m CPU but has a 1000m limit, hitting 500m actual usage shows 200% utilization against the request, triggering aggressive scale-up even though you are only at 50% of the limit. Always tune requests to reflect true baseline consumption before configuring HPA thresholds.
Practical HPA configuration for 2026
Modern HPA manifests use autoscaling/v2 API version. Here is a production-ready example for a Laravel queue worker scaled by custom RabbitMQ queue length:
<!-- apiVersion: autoscaling/v2 -->
<!-- kind: HorizontalPodAutoscaler -->
<!-- metadata: -->
<!-- name: laravel-queue-worker-hpa -->
<!-- spec: -->
<!-- scaleTargetRef: -->
<!-- apiVersion: apps/v1 -->
<!-- kind: Deployment -->
<!-- name: laravel-queue-worker -->
<!-- minReplicas: 2 -->
<!-- maxReplicas: 20 -->
<!-- metrics: -->
<!-- - type: External -->
<!-- external: -->
<!-- metric: -->
<!-- name: rabbitmq_queue_messages -->
<!-- selector: -->
<!-- matchLabels: -->
<!-- queue: invoice-processing -->
<!-- target: -->
<!-- type: AverageValue -->
<!-- averageValue: "50" -->
<!-- behavior: -->
<!-- scaleUp: -->
<!-- stabilizationWindowSeconds: 30 -->
<!-- policies: -->
<!-- - type: Pods -->
<!-- value: 4 -->
<!-- periodSeconds: 60 -->
<!-- scaleDown: -->
<!-- stabilizationWindowSeconds: 300 -->
<!-- policies: -->
<!-- - type: Pods -->
<!-- value: 2 -->
<!-- periodSeconds: 120 --> The behavior block is critical. Without it, HPA uses legacy defaults that scale up aggressively but scale down too slowly (or vice versa depending on version). Setting a 5-minute stabilization window for scale-down prevents flapping when traffic has natural valleys. For eCommerce platforms processing seasonal bursts during Dashain or Black Friday, this damping prevents premature termination of workers mid-job.
When should you use Vertical Pod Autoscaler instead of adding replicas?
Vertical Pod Autoscaler addresses a problem HPA cannot solve: inefficient resource allocation per pod. VPA observes actual CPU and memory consumption over time and recommends (or enforces) updated resource requests and limits. This is invaluable for workloads where horizontal scaling is ineffective or impossible.
VPA modes and safety constraints
VPA operates in three modes, and choosing wrong causes outages:
- Off (Recommendation Only): VPA analyzes usage and exposes recommended values via its status field. No automatic changes. This is the only safe starting point for existing production workloads.
- Initial: Sets resources only at pod creation time. Existing pods retain their original specs until restarted manually. Safe for gradual adoption.
- Auto: Recreates pods whenever recommendations deviate significantly from current requests. This guarantees optimal sizing but causes restarts. Never enable Auto on single-replica stateful services or databases without understanding the disruption.
In my experience maintaining legal-tech portals with variable document processing loads, VPA in recommendation mode revealed that our PDF generation containers were requesting 2Gi memory but consistently using only 400Mi, while occasionally spiking to 1.8Gi. The initial static requests were either wasteful or dangerously tight. VPA provided the data to set accurate baselines before we ever considered auto-mode.
The HPA-VPA conflict you must prevent
Critical rule: Never run VPA in Auto mode on the same metric dimension as HPA. If HPA scales on CPU utilization and VPA simultaneously adjusts CPU requests, they enter a destructive feedback loop. VPA increases requests → utilization drops → HPA scales down → fewer pods handle load → utilization spikes → HPA scales up → VPA sees high usage and increases requests again.
The supported pattern is: use VPA to right-size memory (which HPA rarely scales on reliably due to OOMKill risks), and use HPA to scale replicas based on CPU or custom metrics. Alternatively, use VPA in Off mode purely as a recommendation engine feeding manual tuning or GitOps pipelines. Teams building scalable product catalog systems often find this hybrid approach balances automation with predictability.
How does Cluster Autoscaler interact with HPA and VPA in production?
Cluster Autoscaler (CA) operates at the infrastructure layer, completely independent of pod-level metrics. It watches for pods stuck in Pending state due to insufficient resources and provisions new nodes accordingly. Conversely, it identifies underutilized nodes and removes them after a configurable grace period. CA is what makes cloud-hosted Kubernetes economically viable for variable workloads.
The dependency chain matters
Understanding the causal chain prevents debugging nightmares:
- HPA decides to scale from 5 to 15 replicas based on queue depth.
- Scheduler attempts to place 10 new pods but finds no node with sufficient allocatable resources.
- Pods enter Pending state with
Unschedulablecondition. - Cluster Autoscaler detects unschedulable pods matching its node group configuration.
- CA requests new nodes from the cloud provider API.
- Nodes join the cluster, pods schedule, HPA target is satisfied.
If any link breaks, your application fails silently. Common failure points include: CA misconfigured node group labels not matching pod node selectors, cloud provider quota exhaustion, or CA's --scale-down-delay-after-add being too long causing prolonged pending states during rapid scale-ups. On projects using regional cloud providers with limited instance availability, I always configure fallback node groups with different instance types to prevent single-SKU stockouts from blocking autoscaling entirely.
Cost implications of uncoordinated scaling
Without proper integration, CA can over-provision massively. If VPA in Auto mode suddenly doubles memory requests across all pods during a recommendation update, existing nodes become insufficient. CA adds nodes. Then VPA revises downward. Nodes are now underutilized but CA's scale-down delay keeps them running for 10+ minutes. Repeat this cycle hourly and your monthly bill inflates 30-40% without serving additional traffic.
Mitigation strategies include setting VPA update policies to Recreate only during maintenance windows, configuring CA's --scale-down-utilization-threshold conservatively (0.5-0.6 instead of default 0.5), and using priority classes to ensure critical workloads preempt batch jobs during resource contention rather than triggering unnecessary node additions.
| Feature | HPA | VPA | Cluster Autoscaler |
|---|---|---|---|
| Scaling Dimension | Pod replica count | Pod CPU/memory requests | Node count per node group |
| Primary Trigger | Metric threshold breach | Historical usage deviation | Unschedulable pods / underutilized nodes |
| Safe With Others? | Yes, if VPA avoids same metric | Only in Off/Initial mode with HPA | Yes, responds to HPA/VPA outcomes |
| Disruption Risk | Low (new pods are additive) | High in Auto mode (pod recreation) | Medium (node drain + pod eviction) |
| Best For | Stateless web/API workers | Right-sizing, memory-bound apps | Cloud cost optimization, elastic capacity |
| 2026 Stable API | autoscaling/v2 | autoscaling.k8s.io/v1 | Provider-specific (no k8s-native CRD) |
What are the operational gotchas when combining all three autoscalers?
Theory suggests clean separation; reality delivers edge cases. After years of debugging production clusters, these patterns recur consistently:
Startup races and cold-start penalties
When HPA triggers scale-up and CA simultaneously provisions nodes, total time-to-ready includes: cloud VM boot (60-180s), kubelet registration (10-30s), image pull (variable), and application readiness probe passage. For Java or .NET applications with 30+ second startup times, end users experience degraded latency for 3-5 minutes during major scale events. Solutions include provisioned throughput node pools, pre-pulled images via DaemonSets, and HPA scaleUp.policies configured for burst capacity that assumes nodes already exist.
Memory-only workloads defeating HPA
Applications that consume memory proportionally to load but maintain constant CPU (e.g., caching layers, in-memory analytics) cannot use CPU-based HPA effectively. Memory-based HPA is dangerous because exceeding memory limits causes OOMKills rather than graceful degradation. The correct pattern is VPA in recommendation mode establishing accurate memory baselines, combined with custom-metric HPA scaling on business-relevant signals like cache hit ratio or active sessions. This requires investing in observability infrastructure upfront but prevents both under-scaling crashes and over-scaling waste.
Testing autoscaling without production incidents
Never validate autoscaling behaviour exclusively in production. Use tools like k6 or Locust to generate synthetic load in staging clusters that mirror production node sizes and autoscaler configurations. Crucially, test scale-down paths as thoroughly as scale-up; many teams discover broken scale-down logic only after receiving unexpected bills. Implement monitoring alerts for persistent Pending pods (>2 minutes), VPA recommendation drift (>50% deviation), and CA failures to provision within SLA windows.
For teams operating in cost-sensitive environments, consider KEDA (Kubernetes Event-Driven Autoscaling) as a complement to native HPA. KEDA provides event-source-aware scaling (SQS, Kafka, Redis Streams) with built-in idle-to-zero capabilities that native HPA lacks. This eliminates baseline costs for truly sporadic workloads while retaining compatibility with Cluster Autoscaler's node management.
Implementing Kubernetes Autoscaling: HPA, VPA and Cluster Autoscaler Safely
Effective Kubernetes Autoscaling: HPA, VPA and Cluster Autoscaler implementation requires treating each component as a specialized tool rather than a universal solution. Start with HPA for stateless services using meaningful custom metrics, add VPA in recommendation-only mode to establish resource baselines, and deploy Cluster Autoscaler with conservative scale-down policies aligned to your cloud provider's billing granularity. Document your scaling policies alongside application code, review them quarterly against actual usage patterns, and resist the temptation to enable every autoscaling feature simultaneously. The goal is predictable performance at sustainable cost, not maximum automation for its own sake.
If your team needs hands-on guidance implementing these patterns for production workloads, or if you are evaluating whether Kubernetes autoscaling fits your current architecture, reach out to discuss your specific requirements. Proper autoscaling configuration pays for itself within weeks through avoided over-provisioning and prevented outages.

