Skip to main content
emnode
Cost

Tune the AKS cluster autoscaler for rapid scale-down

One change to a cluster-wide profile: stop paying for AKS nodes that emptied out minutes ago. By default a node has to sit unneeded for ten minutes before the autoscaler removes it, and scale-down pauses for ten minutes after every scale-up. Tighten those timers and you stop renting idle compute you are not using.

14 min·10 sections·AZURE

Last reviewed

Tuning the autoscaler for rapid scale-down: the basics

Why does an AKS cluster keep paying for nodes it has finished with?

The AKS cluster autoscaler adds nodes when pods cannot be scheduled and removes nodes when they sit underused. The adding is fast, because a stuck pod is a visible problem. The removing is deliberately slow, because Microsoft ships conservative defaults so that a brief lull does not rip a node out from under a workload that is about to need it again. By default a node has to be unneeded for ten minutes before it becomes eligible for removal, and scale-down evaluation pauses for ten minutes after any scale-up. On a cluster that scales up and down through the day, that conservatism quietly leaves nodes running, and billed, long after the work that justified them has finished.

Azure Advisor surfaces exactly this as a cost recommendation: 'Fine-tune the cluster autoscaler profile for rapid scale down and cost savings'. It applies to the managed cluster itself and its point is plain in Microsoft's own words: a rapid scale-down configuration means more aggressive node removal, which means less idle node cost. The autoscaler profile is a set of cluster-wide timers and thresholds, and the defaults are tuned for safety on a workload that scales rarely, not for cost on a workload that scales often.

This is not a misconfiguration to clean up, it is a default to revisit. The settings that drive the bill are scale-down-unneeded-time, how long a node must look idle before it is eligible to go, scale-down-delay-after-add, how long scale-down sleeps after a scale-up, and scale-down-utilization-threshold, the utilisation below which a node counts as a candidate at all. Shorten the timers and you return empty nodes to Azure sooner. The work is to decide how aggressive is safe for the way each cluster actually scales, then set one profile and let it run.

In this lesson you will learn how the AKS cluster autoscaler decides when to remove a node, which profile settings keep idle nodes running longer than they need to, and how to tune them for rapid scale-down without destabilising a cluster that scales frequently. You will see how to read the current profile, how to apply a safer-but-faster one with the az CLI or Bicep, and how to tell which of your clusters will actually save from the change.

Fun fact

Ten minutes, then ten more

The AKS autoscaler's caution is doubled up by default in a way that surprises people. A node must be unneeded for ten minutes before it is even eligible for removal, but scale-down evaluation also pauses for ten minutes after any scale-up anywhere in the cluster. So on a cluster that scales up even occasionally, the clock that would retire an idle node keeps getting reset, and a node that emptied out can comfortably outlive its usefulness by far longer than the headline ten-minute figure suggests. The defaults are inherited straight from the open-source Kubernetes cluster autoscaler, which was tuned for safety across every imaginable cluster, not for the Azure bill of yours.

Finding the idle node cost in a spiky cluster

Priya runs the platform team for a product that does a heavy nightly batch run and a daytime traffic peak. The AKS cluster scales from three nodes to a dozen and back several times a day. Advisor has flagged the cluster autoscaler recommendation, and the monthly node bill looks higher than the workload should justify.

Before changing anything, Priya reads the current autoscaler profile to see which timers are still at their conservative defaults, so the team can reason about how long an emptied node currently lingers.

Read the live autoscaler profile for the cluster. The defaults are what keep emptied nodes running longer than they need to.

$ az aks show --resource-group myResourceGroup --name myAKSCluster --query "autoScalerProfile.{unneeded:scaleDownUnneededTime, afterAdd:scaleDownDelayAfterAdd, scan:scanInterval, util:scaleDownUtilizationThreshold}" -o table
Unneeded AfterAdd Scan Util
---------- ---------- ------ -----
10m 10m 10s 0.5
# Still on defaults: an emptied node waits 10m to qualify, and scale-down sleeps 10m after every scale-up.

On a cluster that scales up several times a day, these two ten-minute timers are where the idle node cost hides. They are safe defaults, not tuned ones.

How the autoscaler decides a node can go, and why it waitsdeep dive

The autoscaler walks the cluster on a loop set by scan-interval, ten seconds by default, and marks a node as a scale-down candidate when the sum of CPU and memory requests of the pods on it, divided by the node's allocatable capacity, falls below scale-down-utilization-threshold, which defaults to 0.5. A candidate node is not removed straight away. It must stay unneeded continuously for scale-down-unneeded-time, ten minutes by default, before it is actually drained and deleted. Note this is driven by pod requests, not live usage: a node packed with pods that request half their capacity but use almost none still looks busy to the autoscaler, which is why right-sizing requests and tuning scale-down work together.

Two more timers gate the whole process. scale-down-delay-after-add, ten minutes by default, pauses all scale-down evaluation after any scale-up, so a single new node anywhere resets the clock for every idle node in the cluster. scale-down-delay-after-failure, three minutes by default, backs off after a failed attempt. The combined effect on a cluster that scales up several times an hour is that emptied nodes persist well past the headline ten-minute figure, because the delay-after-add keeps restarting before the unneeded timer can elapse.

Tuning for rapid scale-down means lowering these timers: a shorter scale-down-unneeded-time so idle nodes qualify sooner, a shorter or zero scale-down-delay-after-add so a scale-up elsewhere does not keep idle nodes alive, and Microsoft's documented aggressive profile also raises scan frequency and max-empty-bulk-delete so many empty nodes can go at once. One critical fact frames the whole exercise: the autoscaler profile is cluster-wide. You cannot set it per node pool, so the values you choose have to be safe for every workload that shares the cluster, and any node pool with the autoscaler enabled starts using the new profile the moment you set it.

What is the impact of leaving the autoscaler on its default timers?

The direct impact is idle node-hours you pay for. AKS bills the underlying virtual machines for as long as they exist, so every minute an emptied node lingers past the point it was needed is compute you rent and do not use. On a cluster that scales up and down through the day, the conservative default timers mean post-peak nodes routinely outlive their work, and that overhang lands on the bill every single day for the life of the cluster.

The saving from fixing it is recurring and compounding, but it is not uniform. A spiky cluster, batch runs, CI fleets, daytime traffic peaks, has a large pool of reclaimable idle capacity and benefits the most. A steady-state cluster has almost nothing to reclaim and barely moves. The impact of inaction is therefore largest exactly where it is easiest to miss: a cluster that scales cleanly looks healthy on every dashboard while quietly carrying an idle-node tax that no single graph makes obvious.

There is a real cost to over-correcting, and it is the reason the defaults are conservative. Scale down too aggressively on a cluster that scales out and in within short intervals and you can remove a node moments before the load returns, paying for the change in slower node provisioning and briefly unschedulable pods. Microsoft's own guidance is explicit that aggressive scale-down is not recommended for those rapidly oscillating clusters, and that raising scale-down-delay-after-add keeps a node around long enough to absorb returning work. The impact to manage is on both sides: idle cost if you leave it, provisioning churn if you overdo it.

How do you tune the autoscaler for rapid scale-down safely?

Treat this as a deliberate tuning exercise on the clusters that will benefit, not a blanket setting cranked to its minimum everywhere. The profile is cluster-wide, so the values have to be safe for every workload on the cluster.

1. Identify the clusters that will actually save

The saving lives on clusters that scale up and down through the day: batch fleets, CI, daytime traffic peaks. Read the current profile and confirm the scale-down timers are still on their ten-minute defaults. Steady-state clusters with little scaling have almost nothing idle to reclaim, so tune those last or not at all.

2. Pick timer values that match how the cluster scales

Lower scale-down-unneeded-time so an emptied node qualifies for removal sooner, and lower scale-down-delay-after-add so a scale-up elsewhere stops keeping idle nodes alive. The right values track the cadence of the workload: a node should outlive a typical lull but not a typical idle stretch. Do not simply copy the most aggressive profile onto a cluster that oscillates every few minutes.

3. Apply the profile and watch a full cycle

Set the profile once. Because it is cluster-wide, every autoscaler-enabled node pool starts using it immediately. Then observe a full daily cycle: confirm idle nodes are released faster and, critically, that you are not removing nodes moments before load returns and paying it back in slower provisioning and unschedulable pods. Dial the timers back up if you see churn.

4. Codify it in infrastructure as code

Move the tuned profile into Bicep or your IaC of choice so it is the same on every deployment and survives a cluster rebuild. Encoding the autoScalerProfile in template form means the saving is the default for new clusters of the same shape, not a manual step someone has to remember to repeat.

# Tune the cluster-wide autoscaler profile for faster scale-down.
# Idle nodes qualify in 5m (default 10m) and a scale-up elsewhere no longer
# pauses scale-down for 10m. Verify against your own scale cadence first.
az aks update \
  --resource-group myResourceGroup \
  --name myAKSCluster \
  --cluster-autoscaler-profile scan-interval=20s,scale-down-delay-after-add=2m,scale-down-delay-after-failure=1m,scale-down-unneeded-time=5m,scale-down-unready-time=5m,max-empty-bulk-delete=100

# Read the profile back to confirm it applied.
az aks show --resource-group myResourceGroup --name myAKSCluster \
  --query autoScalerProfile -o jsonc

# Equivalent in Bicep (autoScalerProfile uses hyphenated string keys):
#
# resource aks 'Microsoft.ContainerService/managedClusters@2025-08-01' = {
#   name: 'myAKSCluster'
#   location: location
#   properties: {
#     autoScalerProfile: {
#       'scan-interval': '20s'
#       'scale-down-delay-after-add': '2m'
#       'scale-down-delay-after-failure': '1m'
#       'scale-down-unneeded-time': '5m'
#       'scale-down-unready-time': '5m'
#       'max-empty-bulk-delete': '100'
#     }
#     // ... agentPoolProfiles, dnsPrefix, etc.
#   }
# }

Quick quiz

Question 1 of 5

Azure Advisor flags 'Fine-tune the cluster autoscaler profile for rapid scale down and cost savings'. What is the saving mechanism it is pointing at?

You can now read the AKS autoscaler profile, see where the conservative default timers leave idle nodes running and billed longer than they need to be, and tune scale-down-unneeded-time and scale-down-delay-after-add for rapid scale-down on the clusters that actually scale. You know the profile is cluster-wide, that the saving concentrates on spiky workloads, and that the one trade to respect is not over-tuning a cluster that oscillates every few minutes.

Back to the library