
Table of Contents
By Khimananda Oli | Last reviewed: August 2026
Horizontal Pod Autoscaling in Kubernetes is the primary mechanism for dynamically adjusting application capacity to match real-time demand without manual intervention. When traffic spikes hit your Nepal-based e-commerce platform during a festival sale or a global SaaS product experiences viral growth, static replica counts either waste money or cause outages. This guide provides the exact configuration patterns, metric strategies, and tuning parameters I use in production environments to ensure Kubernetes autoscaling actually works when it matters most.
How does Horizontal Pod Autoscaling in Kubernetes calculate replica counts?
The HPA controller runs inside the kube-controller-manager and executes a reconciliation loop, typically every 15 seconds. During each cycle, it queries the Metrics API for current utilization values and applies a straightforward proportional algorithm. Understanding this math prevents the most common misconfiguration errors I see in audit engagements.
The core scaling formula
The controller uses this formula to determine desired replicas:
desiredReplicas = ceil[currentReplicas * (currentMetricValue / desiredMetricValue)] If you have 4 pods averaging 80% CPU against a 50% target, the calculation becomes ceil[4 * (80/50)] = ceil[6.4] = 7. The controller patches the Deployment's replica count to 7. Note the ceiling function — Kubernetes always rounds up to avoid under-provisioning. This also means small fluctuations near the threshold can trigger scaling events, which is why stabilization windows matter.
Metric types and sources
- Resource metrics: CPU and memory utilization from the Metrics Server. These are available by default in most managed clusters (EKS, AKS, GKE) and require no additional infrastructure.
- Custom metrics: Application-specific values like requests-per-second, queue depth, or active connections. Requires Prometheus Adapter or similar to expose the custom.metrics.k8s.io API.
- External metrics: Cloud provider metrics such as SQS queue length, Pub/Sub backlog, or CloudWatch alarms. Requires the external.metrics.k8s.io API and appropriate adapter.
In practice, I recommend starting with CPU for stateless web services and reserving custom metrics for worker pools where CPU correlates poorly with actual load. Memory-based scaling is risky for applications with lazy garbage collection or connection pooling, as memory often doesn't release promptly after load drops.
How do you configure Horizontal Pod Autoscaling in Kubernetes with YAML?
Modern clusters use the autoscaling/v2 API exclusively. The legacy v1 API supports only CPU and lacks multi-metric support. Below is a production-grade manifest I deploy for Laravel API backends handling variable traffic across Nepal and international regions.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-backend-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-backend
minReplicas: 3
maxReplicas: 20
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Pods
value: 4
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 2
periodSeconds: 120
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75 Critical configuration details
- Always set resource requests on containers. HPA calculates utilization as
currentUsage / requestedAmount. Without requests, percentage-based targets fail silently and the HPA reports<unknown>metrics. This is the number one issue I troubleshoot. - Set minReplicas ≥ 2 for production. Single-replica minimums create availability gaps during node failures or rolling updates. For SOC 2 compliance, I enforce minReplicas ≥ 3 across all customer-facing services.
- Define explicit scaling behavior. Default stabilization windows (300s down, 0s up) are too aggressive for scale-up and too slow for scale-down in many workloads. The example above allows faster scale-up (60s window, max 4 pods/min) while preventing flapping on scale-down (300s window, max 2 pods removed per 2 minutes).
- Use multiple metrics conservatively. The HPA picks whichever metric demands the highest replica count. Combining CPU and memory provides safety, but ensure both thresholds reflect genuine saturation points rather than arbitrary numbers.
When should you use custom metrics instead of CPU for Horizontal Pod Autoscaling in Kubernetes?
CPU utilization is a lagging indicator for many modern workloads. I switch to custom metrics when any of these conditions apply:
| Workload Type | CPU Correlation | Better Metric | Implementation |
|---|---|---|---|
| API gateways / reverse proxies | Poor (I/O bound) | Requests/sec, latency p95 | Prometheus + Adapter |
| Queue workers | Very poor | Queue depth, message age | SQS/RabbitMQ exporter |
| WebSocket / gRPC streaming | Moderate | Active connections | App instrumentation |
| ML inference servers | Variable | GPU utilization, batch queue | DCGM exporter |
| Database connection poolers | Misleading | Pool utilization %, wait time | PgBouncer exporter |
Setting up Prometheus Adapter for custom metrics
For teams already running Prometheus monitoring, the Prometheus Adapter translates PromQL queries into the custom.metrics.k8s.io API. A minimal adapter configuration mapping HTTP request rate looks like:
prometheusAdapter:
rules:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "^(.*)_total$"
as: "${1}_per_second"
metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)' This exposes http_requests_per_second as a namespaced pod metric usable directly in HPA specs. Verify with kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/production/pods/*/http_requests_per_second" before wiring it to autoscaling.
What are common pitfalls and debugging steps for Horizontal Pod Autoscaling in Kubernetes?
After years of operating clusters for fintech and SaaS clients, these are the failure modes I encounter repeatedly:
HPA shows <unknown> or fails to scale
- Missing resource requests: Run
kubectl describe deployment <name>and verify every container hasresources.requests.cpuandmemorydefined. Percentage targets cannot function without them. - Metrics Server unavailable: Check
kubectl top nodes. If it errors, the Metrics Server pod may be crashed, RBAC may be misconfigured, or the API service registration is stale. On self-managed clusters, reinstall with official manifests rather than outdated Helm charts. - Namespace mismatch: The HPA must reside in the same namespace as its target Deployment. Cross-namespace references are not supported.
Scaling is too slow or too aggressive
If pods take too long to start, the bottleneck isn't HPA — it's image pull time, readiness probe duration, or application startup. Profile your cold start with kubectl get events and optimize the container image using multi-stage builds. For overly aggressive scaling, increase the scaleUp stabilization window and add rate-limiting policies. Remember that each new pod consumes cluster resources; unbounded maxReplicas can exhaust nodes and trigger cascading failures.
Flapping between scale-up and scale-down
This occurs when the target threshold sits too close to normal operating variance. If your app idles at 45% CPU and targets 50%, minor jitter triggers constant scaling. Either raise the target to 65–70% or implement wider stabilization windows. I also recommend anomaly detection on metrics to distinguish genuine load shifts from noise before they reach the HPA.
Implementing Horizontal Pod Autoscaling in Kubernetes for Production Reliability
Horizontal Pod Autoscaling in Kubernetes delivers genuine operational leverage only when configured with discipline. Start with conservative CPU targets and explicit behavior policies, validate metrics availability before going live, and layer custom metrics only after proving CPU insufficient. Pair HPA with Cluster Autoscaler to ensure underlying capacity keeps pace, and never treat autoscaling as a substitute for proper capacity planning or performance optimization. If your team needs help designing compliant, audit-ready autoscaling architectures that survive real traffic and regulatory review, reach out to discuss your infrastructure.