Horizontal Pod Autoscaler in Kubernetes: Scaling Your Pods with Metrics

Horizontal Pod Autoscaler in Kubernetes: Scaling Your Pods with Metrics

Learn how the Horizontal Pod Autoscaler watches CPU, memory, and custom metrics to add or remove pods automatically, how its scaling formula and safety settings work, and how to tune it so your application stays fast under load without wasting money when it is quiet.

Imagine a supermarket that opens more checkout lanes when queues grow long and closes them when the shop empties. A manager who watches the queues all day and shouts “open another lane” is a good manager, but a tired one, and no manager can watch a queue at three in the morning. Now imagine the shop has a smart system that counts the shoppers waiting at each lane every few seconds and opens or closes lanes by itself, following a simple rule. That is the Horizontal Pod Autoscaler. It watches how busy your pods are, and it adds or removes copies of your application automatically, so users are served quickly and resources are not wasted.

1Why Applications Need to Scale Automatically

Traffic is never constant, and a fixed number of pods is always wrong some of the time.

Real applications face changing demand. A shop’s website is quiet at night and crowded during a sale. A news site can be overwhelmed within minutes by a breaking story. A payroll system is idle most of the month and heavily used at the end. If you choose a fixed number of pods, you face an uncomfortable choice. Pick enough for the busiest moment, and you pay for idle capacity almost all the time. Pick enough for the average, and users suffer whenever demand rises above it.

Adjusting the number by hand does not work well either. People cannot watch dashboards around the clock, and they react slowly. By the time someone notices that the application is struggling, users have already been affected. Automation solves this by turning a human reaction into a rule that the cluster follows continuously, in seconds instead of minutes.

Simple Analogy

Think of a restaurant kitchen during a dinner rush. A good head chef calls in extra cooks when orders pile up and sends some home when the rush passes. The chef does not decide by guessing; she looks at the number of tickets waiting. The autoscaler looks at a chosen measure of load, and adds or releases cooks, which are pods, to keep the queue under control.

What automatic scaling offers

Automatic scaling gives you three benefits at once. Users get consistent performance because capacity follows demand. You save money because idle capacity is released. And operations become calmer because nobody needs to adjust replica counts at unsociable hours. The trade-off is that the autoscaler is another moving part, with settings you must understand and tune.

15s
Default time between autoscaler checks
10%
Default tolerance before it acts
5 min
Default wait before scaling down
i
Good to know

This guide assumes you know what a pod and a Deployment are, but every new term is explained when it first appears. We concentrate on the metrics-based behaviour of the autoscaler, which is how most teams use it.

2What Is the Horizontal Pod Autoscaler?

A control loop that changes the number of pod copies based on observed metrics.

The Horizontal Pod Autoscaler, usually shortened to HPA, is a built-in Kubernetes feature. You describe which workload it should manage, what to measure, what target to aim for, and the smallest and largest number of pods allowed. The HPA then runs a control loop that regularly reads the metrics, compares them with the target, and changes the replica count of the workload to bring the measurement back toward the target.

The word horizontal is important. Scaling horizontally means adding or removing copies of the same pod. The alternative, scaling vertically, means making each pod bigger or smaller, by giving it more or less CPU and memory. Both are useful, but they answer different problems. Horizontal scaling is ideal for stateless services that can run many identical copies side by side.

AspectHorizontal ScalingVertical Scaling
What changesThe number of podsThe size of each pod
Best forStateless services that can run many copiesWorkloads that cannot easily be split, or need right-sized requests
Effect on running podsExisting pods keep running, new ones are added or removedPods usually must be restarted to change size
Kubernetes componentHorizontal Pod AutoscalerVertical Pod Autoscaler, an optional add-on
LimitCluster capacity and how well the application spreads across copiesThe size of the largest node
Simple Analogy

Horizontal scaling is hiring more cashiers. Vertical scaling is training one cashier to work faster. Hiring more cashiers works nicely until you run out of counters. Training helps, but one person has limits, and you cannot train someone while they serve a queue.

!
Common Misconception

The autoscaler does not make your application faster or fix a slow one. It only changes how many copies run. If the application has a bottleneck that more copies cannot relieve, such as a saturated database, adding pods will not help and may make things worse.

3The Control Loop: How the HPA Works Step by Step

Observe, compare, decide, act, and repeat.

The autoscaler is a controller that runs inside the cluster’s control plane. About every fifteen seconds by default, it goes around a loop. It reads the current metric values for the pods of each workload it manages. It compares those values with the targets you set. It computes how many pods would be needed to meet the target. Then it adjusts the workload’s desired replica count, subject to safety limits, and the normal Kubernetes machinery creates or removes pods.

sequenceDiagram
    participant H as HPA controller
    participant M as Metrics API
    participant T as Target workload
    participant K as Kubernetes controllers
    loop Every sync period
        H->>M: Read current metrics for the pods
        M-->>H: Values
        H->>H: Compare with target and compute desired replicas
        H->>H: Apply limits, tolerance, and stabilisation
        H->>T: Update desired replica count
        T->>K: Create or remove pods
    end
        
FIG 1 — The autoscaler reads metrics, computes a desired count, and updates the workload on every cycle
1

Find the pods

The autoscaler uses the target workload’s label selector to find the pods it is responsible for.

2

Fetch the metrics

It asks the appropriate metrics interface for the current values, for example CPU usage of each pod.

3

Compute the desired count

It applies a simple formula that compares the current value with the target and scales the replica count in proportion.

4

Apply safety rules

It respects the minimum and maximum, a tolerance band that ignores tiny differences, and rate limits that prevent violent swings.

5

Update the workload

It writes the new replica count through the workload’s scale interface, and the workload’s own controller does the rest.

Simple Analogy

A thermostat works the same way. It reads the room temperature, compares it with the setting, and switches the heater on or off. It does not know how to heat a house; it only decides how much heating is needed. The autoscaler decides how many pods are needed, and the rest of Kubernetes provides them.

4What the HPA Can and Cannot Scale

Only workloads that expose a scale interface can be managed.

The autoscaler works with any workload that supports a scale interface, which is a standard way to read and change a replica count. The most common targets are Deployments, which manage stateless pods, and StatefulSets, which manage stateful ones. ReplicaSets also work, and some custom resources from add-ons do too. You name the target in the autoscaler’s definition, and it takes care of the rest.

Works

Deployment

The most common target. New pods are created or removed by the underlying ReplicaSet as the count changes.

Works

StatefulSet

Supported, but each pod has an identity and often storage. Scaling must respect ordered start-up and the needs of the application.

Works

ReplicaSet and custom resources

Anything exposing the scale interface can be targeted, including many resources defined by add-ons.

Does not

DaemonSet

A DaemonSet runs exactly one pod per node, so there is no replica count for the autoscaler to change.

Does not

Jobs

Jobs run to completion and do not have a steady replica count in the same sense. Other tools scale workers for batch queues.

By default not

Scale to zero

The standard autoscaler keeps at least one pod. Scaling to zero needs an experimental feature or an add-on built for event-driven scaling.

flowchart TD
    HPA[HPA definition] -->|names the target| SR[Scale interface of the target]
    SR --> D[Deployment]
    SR --> S[StatefulSet]
    SR --> R[ReplicaSet]
    SR --> C[Custom resource with scale support]
    D --> P1[Pods created or removed]
    S --> P2[Pods created or removed in order]
        
FIG 2 — The autoscaler changes the replica count through a standard scale interface
i
Stateless Fits Best

Autoscaling is easiest and safest for stateless services, where any pod can answer any request. Stateful workloads can be autoscaled, but you must be sure that adding or removing members is safe for the data and the cluster they form.

5Where the Metrics Come From: Three Metrics APIs

The autoscaler asks different interfaces for different kinds of numbers.

The autoscaler does not measure anything itself. It reads metrics from standard interfaces of the Kubernetes API, and it uses different interfaces for different kinds of data. The first covers basic resource use and is provided by the Metrics Server. The second and third cover richer data and must be provided by an adapter that you install, connecting the cluster to a monitoring system or another source.

InterfaceWhat It CarriesProvided ByExample
Resource metrics interfaceCPU and memory of pods and containersThe Metrics Server, installed as a cluster add-onAverage CPU use of the pods of a web service
Custom metrics interfaceMetrics about Kubernetes objects, such as pods or an IngressAn adapter connected to a monitoring systemRequests per second handled by each pod
External metrics interfaceMetrics from outside Kubernetes, not tied to a cluster objectAn adapter for a queue, cloud service, or monitoring systemNumber of messages waiting in a queue
flowchart TD
    HPA[Horizontal Pod Autoscaler] --> A1[Resource metrics interface]
    HPA --> A2[Custom metrics interface]
    HPA --> A3[External metrics interface]
    A1 --> MS[Metrics Server
reads kubelets] A2 --> AD1[Metrics adapter
reads monitoring system] A3 --> AD2[Event or external adapter
reads queues and services] MS --> K[Kubelets on nodes] AD1 --> PR[Monitoring system] AD2 --> EX[Queues, cloud services]
FIG 3 — Three interfaces let the autoscaler read basic, custom, and external metrics
Simple Analogy

The autoscaler is like a manager who reads three kinds of reports. The first is the standard headcount, which anyone can produce. The second is a detailed report on what each kitchen is doing, which needs a special analyst. The third is a report from outside the company, such as the number of bookings, which needs an external reporter.

!
No Source, No Scaling

If the needed metrics interface is not installed or not working, the autoscaler cannot read anything and will not scale. The most common cause of an autoscaler that shows unknown values is a missing or unhealthy Metrics Server or adapter.

6The Metric Types You Can Scale On

Five kinds of metric, each fitting a different situation.

The autoscaler definition lets you list one or more metrics, and each metric has a type. The type tells the autoscaler where the number comes from and how to interpret it. Choosing the right type is central to good autoscaling, because a metric that does not reflect real load will scale the wrong way at the wrong time.

Type 1

Resource

CPU or memory of the pods, either as a percentage of what each pod requested, or as an average absolute value per pod.

Type 2

Container resource

Like resource, but for one named container in each pod. Useful when a pod has sidecars that would distort the total.

Type 3

Pods

A custom metric measured per pod, such as requests per second. The autoscaler averages it across the pods.

Type 4

Object

A metric about one other Kubernetes object, such as requests per second reported for an Ingress in front of the workload.

Type 5

External

A metric that does not belong to any Kubernetes object, such as the length of a message queue or a cloud service statistic.

Metric TypeInterface UsedTypical Target StyleGood For
ResourceResource metricsAverage utilisation percentage, or average value per podGeneral CPU-bound services
Container resourceResource metricsAverage utilisation of one containerPods with heavy sidecars
PodsCustom metricsAverage value per podRequests per second, active connections per pod
ObjectCustom metricsValue or average value for one objectTraffic measured at an Ingress or gateway
ExternalExternal metricsValue or average value per podQueue length, event backlog, business metrics
Simple Analogy

Deciding how many cooks to call in could be based on how tired the cooks are, which is the resource metric, how many orders each cook handles per minute, which is a pods metric, how long the queue at the front door is, which is an object metric, or how many reservations were booked online, which is an external metric. Different restaurants care about different signals.

i
Start Simple

Begin with CPU utilisation, which needs only the Metrics Server. Move to request rate or queue length when CPU proves a poor indicator of real load, for example in services that wait mostly on the network.

7The Scaling Formula with Worked Examples

One proportional rule sits at the heart of every scaling decision.

The autoscaler uses a simple proportional formula. The desired number of replicas equals the current number of replicas multiplied by the ratio of the current metric value to the desired metric value, and the result is rounded up to the next whole number. In words: if the pods are twice as busy as the target, double the number of pods. If they are half as busy, halve it.

Current PodsCurrent MetricTargetRatioCalculationDesired Pods
480 percent CPU50 percent1.64 times 1.6 equals 6.4, rounded up7
1020 percent CPU50 percent0.410 times 0.4 equals 44
552 percent CPU50 percent1.04Within the tolerance band5, no change
3100 requests per second per pod60 requests per second per pod1.673 times 1.67 equals 55
6Queue of 900 messages50 messages per podUses per-pod average of 1506 times 150 divided by 50 equals 1818
flowchart LR
    A[Current replicas] --> F[Multiply by ratio]
    B[Current metric value] --> R[Ratio of current to target]
    C[Target metric value] --> R
    R --> F
    F --> U[Round up to a whole number]
    U --> L[Apply min, max, and rate limits]
    L --> D[Desired replicas]
        
FIG 4 — The formula is proportional: twice the load means twice the pods
Simple Analogy

Suppose each waiter can comfortably serve five tables. If there are forty tables and currently four waiters, each is handling ten, twice the comfortable load, so you need eight waiters. The formula does exactly this arithmetic, and it always rounds up so nobody is left overloaded.

i
Why Rounding Up

Rounding up errs on the side of having a little more capacity than needed. Being one pod too generous for a moment is far cheaper than being one pod short while users wait.

8Utilisation and Resource Requests

Percent utilisation is measured against what each pod asked for, not against the machine.

When you scale on CPU utilisation, the number the autoscaler uses is a percentage. That percentage is the pod’s actual usage divided by the amount of CPU the pod requested. A pod that requested half a core and is using a quarter of a core is at fifty percent. This has an important consequence: the autoscaler needs pods to declare requests, and the quality of scaling depends on how realistic those requests are.

Request QualityWhat the Autoscaler SeesResult
Realistic requestUtilisation tracks real loadScaling behaves sensibly
Request far too lowUtilisation looks very high even at modest loadScales up too eagerly, wasting resources
Request far too highUtilisation looks low even under heavy loadScales up too late or never
No request at allCannot compute a percentageThe target shows as unknown, and no scaling happens
flowchart TD
    U[Actual CPU use of the pod] --> P[Divide by the pod CPU request]
    R[CPU request declared by the pod] --> P
    P --> V[Utilisation percentage]
    V --> C[Compare with the target percentage]
    C --> D[Decide to scale up, down, or hold]
        
FIG 5 — Utilisation is usage divided by request, so requests shape every scaling decision
Simple Analogy

If a waiter says “I can handle four tables” and is serving three, they are at seventy-five percent. If they had said “I can handle twenty tables,” serving three looks like fifteen percent and nobody would call for help. The claim a waiter makes about their capacity, which is the request, decides how busy they appear.

Pods with several containers

For the standard resource metric, the autoscaler adds up the usage and the requests of all containers in the pod. A pod with a small application container and a large sidecar, such as a logging or proxy container, can therefore show misleading utilisation. Where this matters, the container resource type lets you target a single container, so scaling follows the container that actually carries the load.

!
Common Mistake

Enabling autoscaling on a workload whose containers have no CPU requests, and then wondering why it never scales. Define realistic requests based on observed usage before creating the autoscaler.

9Tolerance, Minimum, and Maximum

Three boundaries stop the autoscaler from overreacting or running away.

Boundary 1

Minimum replicas

The lowest number of pods the autoscaler will ever set. It guarantees a baseline of capacity and availability even when the load is nearly zero.

Boundary 2

Maximum replicas

The highest number of pods it will ever set. It is required, and it protects your budget and your cluster from runaway scaling.

Boundary 3

Tolerance

A band, by default about ten percent either side of the target, within which the autoscaler does nothing. It prevents constant tiny changes.

flowchart TD
    A[Computed desired replicas] --> B{Ratio inside the tolerance band?}
    B -->|Yes| C[Keep current replicas]
    B -->|No| D{Below the minimum?}
    D -->|Yes| E[Use the minimum]
    D -->|No| F{Above the maximum?}
    F -->|Yes| G[Use the maximum]
    F -->|No| H[Use the computed value]
        
FIG 6 — Tolerance and limits shape the final replica count

Choosing the minimum

The minimum should cover your baseline load and your availability needs. A service that must survive the loss of a node or a zone needs at least two or three replicas, spread across failure domains, regardless of how quiet it is. Setting the minimum to one saves money but leaves a single point of failure and a slow response to sudden traffic.

Choosing the maximum

The maximum should reflect the largest load you can serve and afford. It must also fit within your cluster’s capacity and your namespace quotas. If the maximum is higher than the cluster can actually run, extra pods will sit pending, and the autoscaler will believe it has scaled while users still suffer.

Simple Analogy

A restaurant always keeps two waiters on duty, even at three in the morning, which is the minimum. It never calls in more than twenty, because that is all the tables it has, which is the maximum. And the manager ignores tiny changes in the queue, which is the tolerance, so nobody is called in or sent home every minute.

!
Sitting at the Maximum

An autoscaler that stays at its maximum for long periods is a warning sign. Either the limit is too low for real demand, or something else is wrong. Alert on this condition so that people notice before users complain.

10Scaling on Several Metrics at Once

When you list more than one metric, the largest answer wins.

An autoscaler can be given several metrics at the same time, for example CPU utilisation and requests per second. For every metric, it independently computes how many replicas would be needed. It then takes the largest of those numbers. The reasoning is straightforward: if any one measure says the application is under pressure, the application needs more capacity, and it should not be starved just because another measure looks comfortable.

MetricCurrentTargetReplicas Needed by This Metric
CPU utilisation40 percent60 percentLower than current, suggests fewer pods
Requests per second per pod150100Higher than current, suggests more pods
Queue lengthSmallPer-pod targetAbout the same as current
ResultThe autoscaler picks the highest of the three, which comes from the requests metric
flowchart TD
    M1[Metric 1: CPU utilisation] --> C1[Replicas needed: 6]
    M2[Metric 2: requests per pod] --> C2[Replicas needed: 9]
    M3[Metric 3: queue length] --> C3[Replicas needed: 7]
    C1 --> MAX[Take the maximum]
    C2 --> MAX
    C3 --> MAX
    MAX --> R[Desired replicas: 9]
        
FIG 7 — With several metrics, the autoscaler uses the highest number of replicas any metric calls for
Simple Analogy

A restaurant manager considers the queue at the door, the number of unattended tables, and the stress of the kitchen staff. If the kitchen says it needs six cooks, the queue says nine, and the tables say seven, she calls in nine, because the busiest signal decides.

i
Practical Tip

Use multiple metrics to protect against blind spots. CPU alone misses services that wait on other systems, and request rate alone misses heavy requests. Together, they catch both kinds of pressure.

!
Scale-Down Needs Agreement

Because the highest recommendation wins, the number of pods only falls when every metric agrees that fewer pods are enough. A single stubborn metric, such as one that never drops, can prevent scale-down completely.

11Behaviour: Stabilisation Windows and Scaling Policies

Controls that decide how fast the autoscaler may act and how long it waits before shrinking.

A purely proportional rule would react to every wobble in the metrics. Real load is noisy, and reacting to noise causes flapping, where the number of pods rises and falls repeatedly. The behaviour settings let you tame this. They are configured separately for scaling up and for scaling down, since the two directions have different risks. Scaling up too slowly hurts users. Scaling down too quickly causes a shortage moments later.

Setting 1

Stabilisation window

A period during which the autoscaler remembers its recent recommendations and uses the most cautious one. By default, scale-down waits five minutes, and scale-up acts at once.

Setting 2

Policies

Limits on how many pods, or what percentage, may be added or removed within a given period. They cap the speed of change.

Setting 3

Select policy

When several policies apply, this decides whether the one allowing the biggest change, the smallest change, or no change at all is used.

sequenceDiagram
    participant H as HPA
    participant W as Recommendation history
    Note over H: Load falls, HPA computes fewer pods
    H->>W: Record the recommendation
    Note over H,W: Stabilisation window looks at recent recommendations
    H->>H: Use the highest recommendation in the window when scaling down
    Note over H: Scale down only if all recent recommendations agree
    H->>H: Apply rate limit from policies
    H->>H: Change the replica count in small steps
        
FIG 8 — Scale-down waits for a steady lower recommendation, then moves in limited steps
DirectionDefault BehaviourReasonCommon Adjustment
Scale upNo stabilisation wait; can double or add several pods every fifteen secondsUsers are suffering, so react fastLimit growth if new pods overload a shared dependency
Scale downFive-minute stabilisation, and removal at a modest paceA shortage after scaling down is costly, and load often returns quicklyLengthen the wait for spiky traffic, shorten it to save cost
Simple Analogy

A shop manager who sends cashiers home the moment the queue is empty for ten seconds will call them back a minute later. A wiser manager waits several minutes of steady quiet before sending anyone home, and sends them one at a time.

i
Practical Tip

If your traffic has predictable sharp peaks, lengthen the scale-down window so the capacity built for one peak is still there when the next wave arrives, and limit how aggressively pods are removed.

12Unready Pods, Missing Metrics, and Start-Up

New and unhealthy pods can distort the numbers, so the autoscaler treats them carefully.

When a pod has just started, its early CPU use is often unusually high, because it is loading code and warming caches, and unrepresentative of steady work. When a pod is not ready, it is not receiving traffic, so its usage says little about load. And sometimes metrics for a pod are simply missing. If the autoscaler took all of these numbers at face value, it could make poor decisions, for example adding pods because new pods look busy while starting.

SituationHow the Autoscaler Treats ItWhy
Pod started very recentlyIts early CPU numbers are ignored for an initial period, and it is not counted as ready until its readiness delay has passedStart-up spikes are not real load
Pod not readyTreated as using none of the target when scaling upPrevents a runaway of new pods that are still starting
Pod missing metricsAssumed to use none of the target when scaling up, and all of it when scaling downErrs on the side of caution in both directions
Pod being deletedLeft out of the calculationIt is on its way out
sequenceDiagram
    participant H as HPA
    participant P as New pod
    participant M as Metrics
    H->>P: New pod created because of scale-up
    P->>P: Starting, loading, not ready
    H->>M: Read metrics
    M-->>H: Pod shows high start-up CPU
    Note over H: Ignore early readings and treat the pod as not yet contributing
    P->>P: Becomes ready and settles
    H->>M: Read metrics again
    M-->>H: Steady values
    Note over H: Pod now counted normally
        
FIG 9 — Start-up spikes and unready pods are handled specially so they do not trigger extra scale-ups
Simple Analogy

A new waiter on the first shift runs around frantically finding the kitchen and the till. A sensible manager does not conclude the restaurant is too busy and hire more staff just because the newcomer looks exhausted. She waits until he has settled into a normal rhythm.

!
Readiness Drives Speed

The slower your pods become ready, the slower the effective scale-up. A pod that needs two minutes to warm up gives you two minutes of continued overload after the decision. Fast start-up and accurate readiness probes make autoscaling much more effective.

13Custom and External Metrics with Adapters

Going beyond CPU requires a bridge between your monitoring data and the cluster.

CPU and memory are only rough indicators of load. Many services are better measured by how many requests they handle, how many connections are open, or how many jobs wait in a queue. To use such metrics, the cluster needs a component that reads them from wherever they live and presents them through the custom or external metrics interface. This component is called an adapter.

flowchart LR
    APP[Application exposes metrics] --> MON[Monitoring system collects them]
    MON --> AD[Metrics adapter]
    AD --> API[Custom or external metrics interface]
    API --> HPA[Horizontal Pod Autoscaler]
    HPA --> DEP[Deployment replica count]
    DEP --> APP
        
FIG 10 — An adapter carries application-level metrics from monitoring into the autoscaler
Option 1

Monitoring-system adapter

Exposes selected queries from a monitoring system as custom metrics. Good when the useful numbers already live there.

Option 2

Event-driven autoscaler

An add-on that reads from many event sources, such as queues and streams, and can even scale workloads down to zero and back up.

Option 3

Cloud provider adapter

Reads metrics from the cloud platform’s own monitoring service and offers them as external metrics.

Option 4

Custom adapter

For unusual sources, a small program can implement the metrics interface and serve the values you need.

Requests per second per pod

Scaling so that each pod handles roughly a chosen request rate keeps latency stable, and reflects real demand better than CPU for services that spend time waiting on other systems.

Queue length per worker

Workers that process messages from a queue scale so that each worker has a manageable backlog. The backlog is an external metric, and the target is the number of messages per worker.

Active connections or sessions

Services that hold long-lived connections, such as chat or streaming, scale on the number of connections per pod, since CPU may stay low while capacity is exhausted.

i
Keep Metrics Cheap and Reliable

The autoscaler depends on these metrics every fifteen seconds. Make sure the queries are fast, the adapter is highly available, and the numbers are stable, because a broken or noisy metric leads directly to broken or noisy scaling.

14Reading HPA Status, Conditions, and Events

The autoscaler tells you what it thinks and why, if you know where to look.

Every autoscaler reports its own state. A quick listing shows the current metric value against its target, the minimum, maximum, and current replica counts. A detailed view adds conditions and recent events that explain what the autoscaler did and why it did not do something. Learning to read these is the fastest route to understanding any autoscaling behaviour.

Condition 1

Able to scale

Says whether the autoscaler is allowed to change the replica count right now, or is waiting because of recent scaling or stabilisation.

Condition 2

Scaling active

Says whether the autoscaler can read metrics and compute recommendations. When false, it is blind, and the message explains why.

Condition 3

Scaling limited

Says whether the desired count was held back by the minimum or maximum. It signals that limits are constraining the outcome.

What You SeeWhat It MeansWhat To Do
Target shows unknownThe autoscaler cannot compute the metricCheck requests on pods, the Metrics Server, and adapters
Message about missing request for CPUPods have no CPU requestDefine realistic requests in the pod template
Message about failing to get metricsThe metrics source is unavailableCheck the API service and the Metrics Server or adapter
Current replicas equal the maximumThe upper limit is reachedCheck demand and raise the maximum if justified
Current replicas equal the minimum with low loadNormal quiet stateNothing, unless the minimum is too costly
Desired differs from current for a long timeConstraints such as quotas, pending pods, or policiesCheck pod events and cluster capacity
Simple Analogy

The status view is the autoscaler’s notebook. It writes down what it measured, what it wanted to do, and why it held back. A manager who reads the notebook understands the decisions instead of guessing.

i
Practical Tip

When you first create an autoscaler, watch its status while you apply artificial load. Seeing the values, the desired count, and the events change together builds an understanding that no document can match.

15Working with Deployments: Replica Counts and Rollouts

Two owners of the replica count cause a fight.

A Deployment normally has its own replica count, written in its definition. When an autoscaler manages the Deployment, it takes over that number. If your deployment manifests still contain a fixed replica count and you apply them regularly, each application of the manifest resets the count to the fixed value, undoing the autoscaler’s work until it corrects again. The result is a sudden drop in pods every time you deploy, a common and painful surprise.

sequenceDiagram
    participant H as HPA
    participant D as Deployment
    participant P as Pipeline applying manifests
    H->>D: Set replicas to 12 for current load
    P->>D: Apply manifest containing replicas 3
    D->>D: Scale down to 3 pods immediately
    Note over D: Users suffer a sudden capacity drop
    H->>D: Sets replicas back to 12 after next check
        
FIG 11 — A fixed replica count in the manifest fights the autoscaler on every deployment

Good practice

  • Leave the replica count out of the manifest of an autoscaled workload
  • Let the autoscaler own the number of pods entirely
  • Use the minimum setting of the autoscaler for the baseline

Common problems

  • Every release resets capacity to a fixed low value
  • Two systems, a pipeline and the autoscaler, disagree constantly
  • Sudden drops during deployments cause brief overload

Rolling updates while autoscaling

Autoscaling and rolling updates can happen at the same time. During a rollout, the Deployment holds two ReplicaSets, and the autoscaler’s change in replicas is distributed between them in proportion. This works well in practice. But it does mean a rollout during peak traffic is riskier, because capacity is being both replaced and adjusted, so avoid deploying at moments of extreme load when you can.

!
Common Mistake

Keeping a replica count in a template or chart values file and applying it on every release. Remove it, so that the autoscaler alone decides how many pods should run.

16HPA with the Cluster Autoscaler, VPA, and Disruption Budgets

Several scaling mechanisms coexist, and each covers a different level.

The Horizontal Pod Autoscaler changes the number of pods. But pods need nodes to run on. If the cluster has no free room, the new pods stay pending, and the scale-up achieves nothing. A second mechanism, the cluster autoscaler, adds nodes when pods cannot be scheduled and removes idle nodes. The two work as a chain: the pod autoscaler asks for more pods, and the cluster autoscaler provides the machines for them.

sequenceDiagram
    participant L as Load
    participant H as HPA
    participant S as Scheduler
    participant C as Cluster autoscaler
    participant N as New node
    L->>H: Metrics rise
    H->>S: Desired pods increased
    S->>S: No room, some pods pending
    S->>C: Pending pods cannot be scheduled
    C->>N: Add a node
    N-->>S: Node ready
    S->>N: Schedule pending pods
    Note over L,N: Capacity is finally available
        
FIG 12 — The pod autoscaler and the cluster autoscaler work as a chain, and node start-up adds delay
MechanismWhat It ScalesReacts ToWorks With HPA By
Horizontal Pod AutoscalerNumber of podsMetrics such as CPU, requests, or queuesDeciding how many pods are needed
Cluster autoscalerNumber of nodesPods that cannot be scheduled, and idle nodesProviding machines for the pods the HPA requests
Vertical Pod AutoscalerSize of pod requestsObserved resource usage over timeRight-sizing requests, but not on the same metric as the HPA
Pod disruption budgetNothing; limits evictionsVoluntary disruptions such as node drainsProtecting availability during node changes, not HPA scale-down
Simple Analogy

The pod autoscaler is the manager calling in more cooks. The cluster autoscaler is the landlord adding kitchen space when the cooks have nowhere to stand. If the manager calls in ten cooks and the kitchen holds only six, four wait in the corridor until more kitchen is built, and building takes time.

!
Do Not Combine on the Same Metric

The vertical autoscaler and the horizontal autoscaler should not both act on CPU or memory for the same workload. One resizes pods while the other counts them, and they can chase each other in circles. Use the vertical one to right-size requests and the horizontal one with custom metrics, or keep it to recommendations only.

i
Disruption Budgets and Scale-Down

Disruption budgets protect against voluntary evictions, such as node drains. They do not restrict the autoscaler from reducing the replica count. Control the speed of scale-down with the behaviour settings instead.

17Choosing the Right Metric

The best metric is the one that rises before users suffer and falls when capacity is no longer needed.

Picking a metric is the most important design choice for an autoscaler. A good metric reflects real load on the application, moves quickly enough to warn you in time, and falls again when the load falls. A bad metric can be flat while users suffer, or stay high after load has gone, making the autoscaler either useless or wasteful.

MetricGood ForWeakness
CPU utilisationCompute-bound services, easy to set up with only the Metrics ServerMisleading for services that mostly wait on other systems
Memory utilisationWorkloads whose memory grows with load and is released afterwardsMany runtimes hold on to memory, so it does not fall, blocking scale-down
Requests per second per podWeb services and APIsIgnores the cost of each request, so heavy requests can be missed
LatencyDirectly reflects user experienceCan rise for reasons that more pods cannot fix, causing pointless scaling
Queue length or lagWorkers processing messages or eventsNeeds an adapter, and targets must consider processing time
Active connectionsLong-lived connection servicesNeeds application metrics and an adapter
flowchart TD
    Q{What limits this service?} -->|Processor time| CPU[CPU utilisation]
    Q -->|Number of requests| RPS[Requests per second per pod]
    Q -->|Backlog of work| QL[Queue length per worker]
    Q -->|Open connections| CON[Active connections per pod]
    Q -->|Memory that is released after load| MEM[Memory utilisation with care]
    CPU --> CHK[Check the metric rises before users suffer]
    RPS --> CHK
    QL --> CHK
    CON --> CHK
    MEM --> CHK
        
FIG 13 — Choose the metric that matches what actually limits your service
Simple Analogy

A bakery could decide when to bake more bread by watching how tired the bakers are, how many customers enter per minute, or how empty the shelves are. The shelves are the most direct signal of trouble, but bakers’ tiredness is easiest to measure. The best choice depends on what really limits the bakery.

!
Memory Is Tricky

Scaling on memory often looks tempting but works poorly. Many programs never return memory to the system after a peak, so utilisation stays high, and the autoscaler refuses to scale down. Use it only for workloads whose memory rises and falls with load.

18Tuning Targets and Understanding Delay

Autoscaling is never instant, so targets must leave room for the wait.

Between a rise in load and the arrival of new capacity, there are several delays. The metrics are collected on an interval. The autoscaler checks on its own interval. New pods must be scheduled, their images pulled, their containers started, and their readiness checks passed. If nodes are needed, that adds minutes. During all this time, the existing pods carry the extra load. The target you choose determines how much spare capacity exists to absorb it.

1

Load rises

Demand increases, and the existing pods start working harder.

2

Metrics are collected

The metrics source picks up the change on its next collection cycle, adding up to about fifteen seconds.

3

Autoscaler decides

On its next check, the autoscaler notices the change and raises the desired count, adding up to another fifteen seconds.

4

Pods are scheduled and started

New pods are placed, images pulled, and containers started, which takes from seconds to minutes.

5

Pods become ready and share the load

Only after passing readiness do the new pods receive traffic and relieve the existing ones.

Target UtilisationHeadroomEffect
Around 50 percentLargeAbsorbs sudden spikes and slow start-up, at higher cost
Around 70 percentModerateA common balance for steady services
Around 90 percentSmallEfficient, but risky if pods start slowly or traffic spikes suddenly
Simple Analogy

If it takes twenty minutes for an extra chef to arrive, the kitchen must keep enough spare capacity to survive those twenty minutes. A kitchen run at ninety percent of its limit will be swamped before help arrives, while one run at fifty percent absorbs the surge.

i
Practical Tip

Choose the target from the speed of your slowest step. The slower pods become ready, or nodes appear, the lower the target should be. Speed up the slow steps, with smaller images and faster start-up, to be able to run at higher utilisation safely.

19Performance and Scale Considerations

The autoscaler itself is light, but its dependencies and side effects are not.

The HPA controller does modest work: it reads metrics and updates a number. Even hundreds of autoscalers add little load to the control plane. The real costs lie in what it depends on and what it triggers. The metrics source must answer quickly for every autoscaler every fifteen seconds. Each scale-up creates pods, which places work on the scheduler, the nodes, the image registry, and any shared services that the new pods connect to.

Advantages

  • Very low overhead on the control plane
  • Scales to many workloads, each with its own autoscaler
  • No extra components for CPU and memory scaling beyond the Metrics Server
  • Responds automatically, around the clock

Disadvantages / Trade-offs

  • Depends on the health of the metrics source
  • Rapid scale-ups can overload databases and other shared services
  • Large numbers of new pods strain image pulls and scheduling
  • Reaction time is limited by collection, checks, and start-up
Tip 1

Protect downstream systems

More pods mean more connections to databases and services. Limit the rate of scale-up, and size connection pools, so growth does not overwhelm shared dependencies.

Tip 2

Keep images small and cached

Smaller images and pre-pulled images on nodes make new pods start faster, which shortens the whole scale-up chain.

Tip 3

Set the maximum wisely

A ceiling that fits cluster capacity and quotas prevents pending pods and protects you from runaway cost caused by faulty metrics.

Tip 4

Avoid oversized numbers of tiny autoscalers

Share settings through templates so that many autoscalers remain consistent and understandable.

20Security Considerations

Whoever controls the autoscaler’s inputs and limits controls your capacity and your bill.

Autoscaling looks like a purely technical feature, but it has security and cost implications. The autoscaler decides how much of the cluster a workload may use. Anyone who can change the autoscaler’s maximum can raise your costs and crowd out other workloads. Anyone who can influence the metrics it reads can trigger scaling, deliberately or not. And the metrics adapters themselves hold credentials to your monitoring systems.

Control who can edit autoscalers

Permission to create or change autoscalers is permission to change capacity and cost. Restrict it with role-based access control, and review changes to maximum values in the same way as changes to budgets.

Protect the metrics pipeline

If an attacker or a buggy application can publish false metrics, it can drive the autoscaler up or down. Limit who may write to the metrics source, and validate what adapters expose.

Set sensible quotas

Namespace resource quotas cap how much an autoscaler can consume, giving a second line of defence against runaway scaling caused by mistakes or attacks.

Secure adapter credentials

Adapters often hold credentials to read from monitoring systems, queues, or cloud services. Give them read-only access, store the credentials as secrets, and restrict where the adapter can be reached.

Think about denial of wallet

A flood of traffic, real or malicious, can make an autoscaler add many pods and generate large costs. Combine autoscaling limits with rate limiting and traffic protection at the edge.

!
Autoscaling Can Amplify Attacks

An automated system that adds capacity on demand will happily pay for an attacker’s traffic. Put protective limits, such as a sensible maximum and edge rate limiting, in front of any workload that scales automatically.

21Troubleshooting and Monitoring Autoscalers

Most autoscaling problems have plain, visible causes.

1

Look at the autoscaler status

Read the current and target values, the desired and current replica counts, and the conditions. Unknown values and messages point to the problem area.

2

Check the metrics source

Confirm that the Metrics Server, or the adapter, is running and that its API service is available. Request usage for the pods directly to see whether data exists.

3

Check requests on the pods

For utilisation targets, confirm every container has a realistic request. Missing requests are the most frequent cause of unknown values.

4

Check whether new pods can actually run

If the autoscaler wants more pods but they stay pending, look for lack of node capacity, quotas, or scheduling constraints.

5

Review behaviour settings

If the autoscaler seems slow or stubborn, check stabilisation windows, policies, and tolerance, which may be holding it back on purpose.

SymptomLikely CauseWhat To Do
Target shows unknownMetrics unavailable or missing requestsFix the metrics source and define requests
Never scales up despite high loadRequests too high, wrong metric, or limits reachedAdjust requests, choose a better metric, review the maximum
Never scales downMemory metric that does not fall, or long stabilisation, or a second metric that stays highReview metrics and the scale-down window
Flaps up and downNoisy metric or too short stabilisationLengthen the scale-down window and smooth the metric
Desired replicas not reachedPending pods because of capacity or quotasAdd capacity, adjust quotas, check the cluster autoscaler
Replicas drop after every deploymentFixed replica count in the manifestRemove the replica count from the manifest
Scales up on start-upStart-up spike or missing readiness delayTune readiness and the initialisation settings
Signal 1

Current versus desired replicas

A persistent gap shows that something blocks scaling, such as pending pods or rate limits.

Signal 2

Time at the maximum

Alert when a workload sits at its maximum for long. It usually means the limit is too low or something is wrong.

Signal 3

Autoscaler unable to read metrics

Alert on the condition that says scaling is inactive, since the autoscaler is then blind.

Signal 4

Scaling frequency

Very frequent changes signal flapping. Track how often replica counts change per hour.

Signal 5

User-facing latency and errors

The final test of autoscaling is whether users stay happy during load changes, so watch these next to the replica count.

22Design Patterns for Autoscaling

Reliable arrangements used in production clusters.

Pattern: Realistic requests first

Measure real usage and set requests accordingly before creating the autoscaler, so that utilisation percentages carry real meaning.

Pattern: Generous minimum, sensible maximum

Set the minimum to cover baseline load and availability across zones, and the maximum to fit cluster capacity and budget, with an alert when the maximum is reached.

Pattern: Fast up, slow down

Allow quick scale-up to protect users, and use a longer stabilisation window and limited pace for scale-down to avoid flapping and shortages.

Pattern: CPU plus a business metric

Combine CPU utilisation with requests per second or queue length so the autoscaler reacts to both computing pressure and real demand.

Pattern: Warm capacity before known events

Raise the minimum ahead of scheduled peaks, such as a sale or a broadcast, and let the autoscaler handle unexpected variation on top.

Pattern: Autoscaling with a healthy chain

Pair the pod autoscaler with a cluster autoscaler, fast readiness, and protected shared dependencies, so each scale-up actually produces working capacity.

flowchart TD
    A[Measure real usage] --> B[Set realistic requests]
    B --> C[Choose metrics that reflect load]
    C --> D[Set minimum, maximum, and behaviour]
    D --> E[Load test the whole chain]
    E --> F[Monitor status and user impact]
    F --> G[Review and adjust regularly]
    G --> A
        
FIG 14 — A continuous loop of measuring, configuring, testing, and reviewing keeps autoscaling healthy

23Anti-patterns to Avoid

Habits that make autoscaling ineffective or dangerous.

ANTI-PATTERN-01 Avoid
Problem

Autoscaling on utilisation with missing or unrealistic requests.

Why It’s Harmful

The autoscaler cannot compute utilisation, or computes a misleading one, so it never scales or scales far too much.

Correct Approach

Measure real usage, set realistic requests, and verify the autoscaler shows real percentages.

ANTI-PATTERN-02 Avoid
Problem

Keeping a fixed replica count in the manifest of an autoscaled workload.

Why It’s Harmful

Every deployment resets the pod count, causing sudden capacity drops that hurt users.

Correct Approach

Remove the replica count from the manifest and let the autoscaler own it.

ANTI-PATTERN-03 Avoid
Problem

Setting the target utilisation very high to save money.

Why It’s Harmful

There is no headroom to absorb spikes while new pods start, so users suffer during every surge.

Correct Approach

Choose a target that leaves room for the slowest step in the scale-up chain.

ANTI-PATTERN-04 Avoid
Problem

Scaling on memory for workloads that never release memory.

Why It’s Harmful

Utilisation stays high after the peak, and the autoscaler refuses to scale down, wasting money.

Correct Approach

Scale on CPU, request rate, or queue length, and use memory only when it truly tracks load.

ANTI-PATTERN-05 Avoid
Problem

Setting a maximum larger than the cluster can host.

Why It’s Harmful

Extra pods stay pending, and the autoscaler appears to have scaled while users still wait.

Correct Approach

Match the maximum to real capacity and quotas, and pair with a cluster autoscaler if growth is needed.

ANTI-PATTERN-06 Avoid
Problem

Running both horizontal and vertical autoscaling on the same resource.

Why It’s Harmful

They chase each other, one changing pod size while the other changes pod count, producing instability.

Correct Approach

Use the vertical autoscaler for recommendations, and keep the horizontal one on custom metrics or a different signal.

ANTI-PATTERN-07 Avoid
Problem

Trusting autoscaling to solve a bottleneck outside the workload.

Why It’s Harmful

More pods can overload a shared database or service, making the outage worse.

Correct Approach

Find the true bottleneck, protect shared dependencies, and limit the pace of scale-up.

24Best Practices and Common Mistakes

A short checklist for dependable autoscaling.

Best Practices

  • Set realistic resource requests before enabling autoscaling
  • Choose metrics that reflect what limits your service
  • Keep a healthy minimum and a sensible, capacity-aware maximum
  • Use fast scale-up and cautious scale-down settings
  • Remove fixed replica counts from autoscaled manifests
  • Pair with a cluster autoscaler and fast readiness
  • Load test the whole chain and monitor status and user impact

Common Mistakes

  • Expecting instant scaling
  • Ignoring the effect of slow start-up and readiness
  • Forgetting that CPU can be a poor indicator for waiting services
  • Never testing scale-down behaviour
  • Letting scale-ups overwhelm databases and other dependencies
  • Not alerting when the maximum is reached
!
Test Down as Well as Up

Teams often test only the scale-up. Also test how the application behaves as pods are removed: in-flight requests, connection draining, and caches. A scale-down that drops requests is a failure even if the scale-up was perfect.

25Real-World Scenarios

How teams use the autoscaler in daily operations.

A retailer surviving a sale

An online shop scales its storefront on CPU utilisation and requests per second, with a raised minimum before the announced start of a sale. When traffic triples, the autoscaler adds pods within a couple of minutes, the cluster autoscaler adds nodes, and customers see no slowdown.

A media company scaling queue workers

A media company processes uploaded videos with worker pods. The autoscaler uses the queue length per worker as an external metric. During busy hours, hundreds of workers run, and at night the count falls to a handful, saving a large share of the compute bill.

A startup fixing an outage after every release

A startup kept a replica count of three in its chart, and every release dropped capacity from dozens of pods to three. After removing the fixed value from the chart, releases no longer caused sudden slowdowns.

A bank protecting its database

A bank’s payment service scaled up quickly and overwhelmed its database with connections. The team limited the rate of scale-up, capped the maximum, and added connection pooling, so growth stayed within what the database could handle.

An operations team finding a stuck maximum

An alert showed a workload sitting at its maximum for days. Investigation revealed a slow memory-driven metric that never fell and a limit set years earlier. Changing the metric and raising the maximum brought both cost and latency down.

26Frequently Asked Questions

Q1What does the Horizontal Pod Autoscaler do?

It automatically changes the number of pods of a workload, up or down, by comparing observed metrics with a target and applying a proportional formula, within a minimum and maximum.

Q2What do I need for CPU-based autoscaling?

A working Metrics Server, realistic CPU requests on the pods, and an autoscaler definition naming the target workload, the target utilisation, and the minimum and maximum replicas.

Q3How is the desired number of replicas calculated?

Multiply the current replica count by the ratio of the current metric to the target metric, and round up. If the ratio is within the tolerance band, nothing changes.

Q4Why does my autoscaler show unknown?

Usually because the pods have no resource requests, or the metrics source is unavailable. Check requests, the Metrics Server or adapter, and the condition messages on the autoscaler.

Q5Can it scale to zero?

Not by default. The standard autoscaler keeps at least one replica. Event-driven add-ons, or an experimental feature, can scale to zero for suitable workloads.

Q6Why does it wait before scaling down?

A stabilisation window, by default five minutes, makes it use the highest recent recommendation. This prevents flapping and shortages when load returns quickly.

Q7Can it use more than one metric?

Yes. It computes a desired count for each metric and uses the largest one, so scale-down happens only when all metrics agree that fewer pods are enough.

Q8Should I keep replicas in my Deployment manifest?

No. A fixed count in the manifest resets capacity on every apply. Leave it out and let the autoscaler own the replica count.

Q9Why did the autoscaler add pods but performance did not improve?

Perhaps the pods are pending for lack of capacity, are slow to become ready, or the true bottleneck is elsewhere, such as a database. Check pod status, readiness, and shared dependencies.

Q10Can I use the horizontal and vertical autoscalers together?

Not on the same CPU or memory metric for the same workload, since they interfere. Use the vertical one for recommendations, or apply them to different signals.

Q11Which metric should I choose?

The one that rises before users suffer and falls when capacity is no longer needed. CPU is a good start for compute-bound services, and request rate or queue length suits many others.

Q12How fast does autoscaling react?

It is never instant. Metric collection, autoscaler checks, pod scheduling, start-up, and readiness all add delay, so leave headroom in your target and consider warming capacity before known peaks.

27Summary and Key Takeaways

The Horizontal Pod Autoscaler is the Kubernetes control loop that matches the number of pods to the load on an application. On a regular cycle, it reads metrics, from the Metrics Server for CPU and memory or from adapters for custom and external signals, compares them with your targets, and applies a proportional formula to compute the desired number of replicas. Tolerance, minimum and maximum limits, stabilisation windows, and scaling policies keep it from overreacting.

Good autoscaling depends on the surroundings as much as on the autoscaler. Pods need realistic resource requests, fast start-up, and accurate readiness checks. The metric must reflect what truly limits the service. The cluster needs room for new pods, or a cluster autoscaler to provide it, and shared dependencies must survive the growth. Manifests must not fight the autoscaler over the replica count. And the whole chain deserves monitoring, alerts, and load tests. Built that way, autoscaling gives you consistent performance and lower costs without anyone watching the dashboards at night.

Key Takeaways

  • It is a proportional control loop — desired replicas equal current replicas times the ratio of current metric to target, rounded up, and checked against tolerance and limits.
  • Requests define utilisation — CPU and memory percentages are measured against pod requests, so realistic requests are essential and missing ones stop scaling entirely.
  • Pick the right metric — start with CPU, and move to request rate or queue length through adapters when CPU does not reflect real load.
  • Fast up, slow down — use behaviour settings so scale-up protects users quickly while scale-down waits for steady low demand to avoid flapping.
  • Autoscaling is never instant — metric collection, checks, scheduling, start-up, and readiness add delay, so leave headroom and warm capacity before known peaks.
  • Do not fight the autoscaler — remove fixed replica counts from manifests, avoid running vertical and horizontal scaling on the same metric, and pair with a cluster autoscaler for node capacity.
  • Protect and observe — set a capacity-aware maximum and quotas, guard shared dependencies and metrics pipelines, and alert on unknown metrics, stuck maximums, and flapping.