# AKS Cost Optimization: A Guide to Reducing Spend in 2026

> Source: <https://cast.ai/blog/aks-cost-optimization/>
> Published: 2026-09-14 12:14:03+00:00

AKS cost optimization is the process of reducing the cost of running Kubernetes workloads on Azure Kubernetes Service (AKS) while meeting performance and availability requirements. It involves rightsizing pod resources, adjusting node capacity through autoscaling, using Azure Spot Virtual Machines for interruption-tolerant workloads, and applying reservations or savings plans to predictable compute usage.

AKS cost optimization is one of the highest-ROI infrastructure investments a DevOps team can make in 2026. According to [Cast AI’s 2026 State of Kubernetes Optimization Report](https://cast.ai/reports/state-of-kubernetes-optimization/), AKS clusters average just 8% CPU utilization and 20% memory utilization. GPU utilization sits at a striking 2%, the lowest of any major cloud provider and a meaningful gap below EKS (5%) and GKE (6%). In practical terms, most AKS clusters run at roughly one-fifth of their provisioned capacity while billing at full price.

This guide covers the concrete steps to close that gap: choosing the right autoscaler, rightsizing pods before scaling, deploying Spot node pools safely, and applying committed-use discounts to the compute you actually need. For the broader Kubernetes context, start with the [Kubernetes cost optimization overview](https://cast.ai/blog/kubernetes-cost-optimization/).

## Key Takeaways

- Cast AI’s 2026 benchmark data shows 69% of CPU and 79% of memory is wasted across AKS fleets (Cast AI 2026 State of Kubernetes Optimization Report).
- GPU utilization on AKS averages 2%, the widest underutilization gap across any major cloud and a significant cost exposure for GPU-heavy workloads (Cast AI 2026 State of Kubernetes Optimization Report).
- Node Auto Provisioning (NAP), now GA on AKS as of mid-July 2025, selects the optimal VM size per pending workload and outperforms Cluster Autoscaler for most production use cases.
- Spot node pools cut compute costs up to 90%, but they require workloads designed to handle a 30-second eviction window.
- Rightsize before you commit: Azure Reserved VM Instances save 48-72%, but only when applied to correctly-sized instances.
- ARM64 nodes (Ampere Altra, Dpls_v5 series) deliver 30-40% better price-performance for CPU-bound workloads like web servers and API services.

## Node Provisioning: Choosing the Right AKS Autoscaler

### Cluster Autoscaler: The Standard Path

Cluster Autoscaler (CA) is the default scaling option for AKS Standard clusters. It scales pre-existing node pools up or down based on pending pod pressure and configurable resource headroom thresholds. CA is mature, well-documented, and straightforward to operate for teams with stable workloads. However, it has a fundamental constraint: every node in a pool uses the same VM size. Therefore, if your cluster hosts bursty batch jobs alongside low-CPU web services, CA cannot dynamically pick a smaller, cheaper VM for the batch work. You define the instance type at pool creation, and CA operates within that boundary.

This rigidity leads to a common pattern: teams create separate pools for different workload classes, which works but adds operational overhead and often leaves gaps where no pool is optimally sized. For simple clusters with homogeneous workloads, CA is a reasonable choice. For anything more complex, consider NAP.

### Node Auto Provisioning: Karpenter Comes to AKS

Node Auto Provisioning (NAP) reached general availability on AKS in mid-July 2025. Under the hood, it runs the Karpenter scheduler and selects from multiple VM sizes dynamically. Instead of scaling a fixed pool, NAP evaluates each pending pod’s resource requirements and selects the most cost-efficient VM type that satisfies them. This results in better bin-packing, lower idle capacity, and faster scale-up for heterogeneous workloads.

NAP is available on both AKS Standard and AKS Automatic tiers. Configuration works through Kubernetes CRDs, not Azure CLI flags. NodePool and NodeClass CRDs define which VM families, zones, and capacities NAP can use. This declarative approach integrates cleanly with GitOps workflows. For teams already familiar with Karpenter on EKS, the mental model transfers directly. See the [EKS cost optimization guide](https://cast.ai/blog/eks-cost-optimization/) for comparison, and the [GKE cost optimization guide](https://cast.ai/blog/gke-cost-optimization/) for how Google Cloud handles the same challenge.

```
# Example: NAP NodePool CRD for AKS
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: general-pool
spec:
  template:
    spec:
      nodeClassRef:
        group: karpenter.azure.com
        kind: AKSNodeClass
        name: default
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand"]
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64"]
        - key: karpenter.azure.com/sku-family
          operator: In
          values: ["D", "E"]
  limits:
    cpu: 1000
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 120s
# AKSNodeClass: references the AKS node image and identity
apiVersion: karpenter.azure.com/v1alpha2
kind: AKSNodeClass
metadata:
  name: default
spec:
  imageFamily: AzureLinux
```

The `karpenter.azure.com/sku-family` requirement lets NAP choose from any D or E-series instance, selecting the optimal size per workload. For ARM64, add `"arm64"` to the arch values.

### AKS Automatic vs Standard: Choosing Your Tier

AKS Automatic includes NAP by default and applies opinionated defaults for security, availability, and node management. It reduces the operational surface area your team needs to manage. For most production teams that want lower overhead and faster time-to-cost-efficiency, AKS Automatic is the right starting point in 2026.

In contrast, AKS Standard gives you complete control over node pool configuration, OS type, taint strategy, and upgrade windows. This matters if you maintain custom VM types, run specific OS configurations, or manage cluster infrastructure through existing Terraform or Bicep pipelines. Choose Standard when your platform engineering team has the capacity to operate it deliberately. Otherwise, AKS Automatic with NAP delivers the faster path to lower spend.

## Rightsize First: Eliminate Waste Before Scaling

Autoscaling only works efficiently when pod resource requests reflect actual usage. Cast AI’s 2026 benchmark data shows 69% of CPU and 79% of memory is wasted across AKS fleets ([Cast AI 2026 State of Kubernetes Optimization Report](https://cast.ai/reports/state-of-kubernetes-optimization/)). Those wasted requests force the scheduler to provision more nodes than the workloads actually need. As a result, your autoscaler spins up capacity to satisfy headroom that never materializes. Fix request sizes first, then tune your autoscaler and commitment strategy.

### AKS Cost Optimization: Start with PromQL Sizing Queries

These queries require at least 14 days of metric retention configured in Prometheus. Most Prometheus installations support this syntax, but verify your retention period with `--storage.tsdb.retention.time=15d` or equivalent. The following two queries produce accurate p95 CPU and p99 memory consumption per container over a 14-day observation window. Use these values to set resource requests, replacing estimates from developers who calibrate at deploy time without real production data.

```
# p95 CPU per container (14-day window)
max by (namespace, container) (
  quantile_over_time(0.95,
    rate(container_cpu_usage_seconds_total{container!="",container!="POD"}[5m])[14d:5m]
  )
)
# p99 memory per container (14-day window)
max by (namespace, container) (
  quantile_over_time(0.99,
    container_memory_working_set_bytes{container!="",container!="POD"}[14d:5m]
  )
)
```

Run these queries before you touch any autoscaler configuration or purchase any reservations. The output often reveals that some containers request 4x what they use at peak, and others are already tight. Treat the p95 CPU result as your request baseline and the p99 memory result as your memory request value. Add a small buffer (10-20%) for safety headroom.

### AKS Cost Analysis Add-on

Before optimizing, you need cost attribution. The AKS Cost Analysis add-on provides namespace-level spend visibility in the Azure portal. Enable it with one command:

```
az aks update --enable-cost-analysis --resource-group <rg> --name <cluster>
```

This surfaces which namespaces drive the most spend and highlights idle node costs separately from workload costs. Use it to prioritize which teams or services to rightsize first. A namespace burning 40% of the cluster budget with 5% actual CPU utilization is the obvious starting point.

### VPA Modes and the HPA Oscillation Problem

Vertical Pod Autoscaler (VPA) on AKS has four operating modes. Off mode generates recommendations without applying them, making it a safe starting point for teams new to VPA. Initial mode applies recommendations only when a pod is created, avoiding mid-run disruptions. Recreate mode applies recommendations by restarting pods as needed. Auto mode applies recommendations on running pods with potential restarts; use this only when pod restarts are acceptable for your workload. Start with Off mode to validate VPA recommendations against your Prometheus data, then graduate to Initial or Recreate on a per-deployment basis once you trust the numbers.

**Caution:** Do not combine VPA Auto mode with HPA scaling on the same CPU or memory metrics. This causes an oscillation loop. The two controllers conflict: VPA shrinks the pod, HPA sees lower utilization and reduces replicas, VPA then grows the pod, and the cycle repeats indefinitely. Instead, use VPA in Off mode as a recommendation engine and configure HPA on custom application metrics or on metrics orthogonal to VPA’s targets. On AKS 1.35 or later (where InPlacePodVerticalScaling is enabled by default), use InPlaceOrRecreate for CPU adjustments without pod restarts. On earlier versions, this requires explicit feature gate enablement, which is not available for managed AKS control planes. This gives you the benefits of both without the oscillation risk.

Platforms like Cast AI automate this sizing cycle continuously, monitoring p95 CPU and p99 memory 24/7 and applying recommendations without manual intervention. For clusters with dozens or hundreds of deployments, continuous automation closes the optimization gap that periodic manual analysis leaves open.

## Spot Node Pools for AKS: Cut Costs Up to 90%

Azure Spot VMs offer up to 90% savings compared to pay-as-you-go pricing. The trade-off is eviction: Azure can reclaim Spot capacity with approximately 30 seconds of best-effort notice. That window is short and requires deliberate termination handling in your application and infrastructure layer. However, for the right workloads, Spot node pools are one of the most effective levers in your AKS cost optimization toolkit.

### Setting Up an AKS Spot Node Pool

Spot pools must be user node pools, not system node pools. System pools run critical cluster components and cannot tolerate eviction. Set the eviction policy to Delete, not Deallocate. Using Deallocate retains the VM object in Azure after eviction and can produce unexpected billing. Use `--spot-max-price -1` to accept the current Spot price up to the pay-as-you-go cap. Note that you cannot change this value after pool creation, so set it deliberately.

```
az aks nodepool add \
  --resource-group <rg> \
  --cluster-name <cluster> \
  --name spotnodepool \
  --priority Spot \
  --eviction-policy Delete \
  --spot-max-price -1 \
  --node-count 1 \
  --enable-cluster-autoscaler \
  --min-count 0 \
  --max-count 20
```

Setting `--min-count 0` enables scale-to-zero, which keeps costs low when the pool is idle. However, the first batch job submitted to a scaled-to-zero pool waits 3-5 minutes for node provisioning. For latency-sensitive workloads, consider `--min-count 1` to keep one Spot node warm.

Apply the taint `kubernetes.azure.com/scalesetpriority=spot:NoSchedule` to the Spot pool and add a matching toleration to the workloads you want scheduled there. Configure the Cluster Autoscaler priority expander to scale Spot pools before on-demand pools. This prevents on-demand capacity from expanding when cheaper Spot capacity is still available. Without the priority expander, CA may add on-demand nodes even when Spot nodes would satisfy the pending pods.

##### Akamai achieves 40-70% cloud savings, boosts engineer productivity

### AKS Cost Optimization with Spot: Workload Fit and PDB Safety

Spot suits specific workload types. Batch jobs, CI/CD runners, stateless web services with two or more replicas, and ML training workloads all tolerate interruption well. In contrast, databases, stateful workloads without persistent volumes, and single-replica services belong on on-demand nodes. Running a PostgreSQL primary on Spot is not a cost strategy; it is an availability incident waiting to happen.

For workloads on Spot, configure a Pod Disruption Budget to protect availability during eviction and cluster upgrades. Use `maxUnavailable: 1` rather than setting `minAvailable` equal to the full replica count. A PDB where `minAvailable` equals the replica count blocks all voluntary disruptions, including cluster version upgrades. For a three-replica deployment, the correct configuration is `maxUnavailable: 1` or `minAvailable: 2`.

```
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-service-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: web-service
```

**Important:** PDB protects only voluntary disruptions such as node drains and cluster upgrades. Azure capacity-driven evictions are involuntary, and they bypass PDB entirely. Design Spot workloads to tolerate sudden termination without relying on graceful shutdown guarantees.

Cast AI’s predictive rebalancing replaces Spot nodes 2-3 minutes before eviction using Azure capacity signals, before the 30-second notice window begins. For a deeper look at Spot strategies across Kubernetes platforms, see the [Kubernetes Spot instances cost optimization guide](https://cast.ai/blog/kubernetes-spot-instances-cost-optimization/).

## Commitments and ARM: Lock In Savings, Maximize Efficiency

Spot handles variable and interruptible workloads well. For the stable compute baseline that always runs regardless of demand, committed-use discounts are the right tool. The sequencing rule is firm: rightsize first, then commit. Purchasing Reserved Instances on overprovisioned nodes locks in waste at a discounted rate, which is a worse outcome than paying on-demand for a correctly-sized instance.

### Reserved VM Instances and Azure Savings Plans

Azure Reserved VM Instances deliver approximately 48% savings on a 1-year term and up to 72% on a 3-year term compared to pay-as-you-go pricing. Azure Savings Plans are capped at 65%. Choose RI for maximum savings on stable workloads. Monthly payment is available, which removes the upfront commitment barrier for teams that cannot make a single lump-sum purchase. Scope reservations at the subscription or resource group level, depending on how your cost centers are structured. Resource group scoping gives finance teams cleaner attribution when multiple clusters share a subscription.

Azure Savings Plans offer comparable savings (up to 65%) with more flexibility. Savings Plans apply across VM families and Azure regions, which matters if your workload footprint shifts over time or if you run multi-region clusters. For teams with variable VM usage or those planning to migrate between VM families, Savings Plans reduce the risk of stranded reservations. A common approach combines both: Reserved Instances for the stable, predictable VM types you always run, and Savings Plans for the flexible remainder.

Additionally, if your organization holds existing Windows Server or SQL Server licenses, Azure Hybrid Benefit stacks on top of Reserved Instances for additional savings. Review your license inventory before purchasing commitments. The combination of Hybrid Benefit and Reserved Instances represents the maximum achievable discount on eligible workloads.

### ARM64: Better Price-Performance for Compatible Workloads

ARM64 instances (Dpls_v5/Ampere Altra) deliver 30-40% better price-performance compared to equivalent Dv5/Dsv5 instances for CPU-bound workloads like web servers and API services. Memory-bound or I/O-heavy workloads may see different results. Test before migrating. The prerequisite is multi-arch container builds. Before migrating a node pool to ARM64, test your images for ARM compatibility. Most Go, Node.js, and Python workloads function without code changes. Java and C++ workloads sometimes require recompilation or configuration adjustments, depending on native dependencies.

Start the migration by identifying one stateless service with stable, well-understood resource usage. Move its node pool to Dpls_v5 and run it in parallel with the x86 deployment for one week. Measure latency, error rates, and actual compute cost over that period. If the results are clean, expand the migration incrementally. Do not migrate databases or stateful workloads to ARM64 without extended parallel testing first.

The sequencing of all these strategies matters. First, rightsize pods using the PromQL queries and the Cost Analysis add-on. Next, add Spot node pools for interruptible workloads. Then evaluate ARM64 for compatible services. Finally, apply Reserved Instances or Savings Plans to the stable baseline. Each step builds on the previous one, and skipping the order reduces the impact of every step that follows.

## Conclusion

The compounding effect of these optimizations is significant. Start with rightsizing to eliminate waste, then layer in Spot pools for workloads that tolerate interruptions. Add ARM64 nodes for CPU-bound services. Finally, apply Reserved Instances or Savings Plans once your baseline is stable. Each step builds on the previous one, and the savings multiply.

Connect Cast AI to your AKS cluster in under 2 minutes to automate rightsizing, Spot orchestration, and reservation planning. No code changes needed. Explore [Kubernetes cost optimization with Cast AI](https://cast.ai/kubernetes-cost-optimization/) and see how these strategies work together to reduce cloud spend.

## Frequently Asked Questions

### How do I reduce AKS costs?

Reduce AKS costs by rightsizing pod resource requests using Prometheus-based p95 CPU and p99 memory metrics, enabling Node Auto Provisioning (NAP) for better VM bin-packing, running interruptible workloads on Spot node pools for up to 90% compute savings, and applying Azure Reserved VM Instances or Savings Plans to your stable baseline. Enable the AKS Cost Analysis add-on to identify which namespaces concentrate the most spend before making changes.

### Which node autoscaler should I use on AKS?

Use Node Auto Provisioning (NAP) for most production workloads. NAP is Karpenter-based, reached GA on AKS in July 2025, and dynamically selects the optimal VM size from multiple instance types based on pending pod requirements. This produces better bin-packing and lower idle capacity than Cluster Autoscaler. Use Cluster Autoscaler only when you have strict requirements around specific VM sizes per pool or need fine-grained control over node pool configuration that NAP’s CRD-based model does not support.

### Are Spot Instances safe for AKS workloads?

Spot Instances are safe for workloads that tolerate interruption: batch jobs, CI/CD runners, stateless web services running two or more replicas, and ML training jobs. They are not safe for databases, single-replica services, or stateful workloads without persistent volumes. Azure provides approximately 30 seconds of best-effort eviction notice. Configure a Pod Disruption Budget with maxUnavailable: 1, but be aware that PDB only protects against voluntary disruptions. Azure capacity-driven evictions bypass PDB entirely. Design Spot workloads to tolerate sudden termination.
