Kubernetes autoscaling tools fall into two groups that solve different problems. Workload autoscalers change how much your application asks for: HPA adds replicas, VPA adjusts CPU and memory requests, KEDA scales on external events. Node autoscalers change what runs underneath: Cluster Autoscaler scales predefined node groups, Karpenter provisions individual nodes matched to pending pods. Most clusters need one from each group. The reason autoscaling alone rarely cuts the bill is that every node autoscaler provisions against what workloads request, and requests run about 69% above actual CPU usage.
Key takeaways
- Two separate problems, two tool categories. Node autoscalers (Cluster Autoscaler, Karpenter) add and remove VMs. Workload autoscalers (HPA, VPA, KEDA) change pod replicas or resource requests. Most clusters need one from each group.
- Karpenter outpaces Cluster Autoscaler on speed and flexibility. Karpenter provisions any instance type in 45–90 seconds and consolidates actively. Cluster Autoscaler is limited to predefined node groups and takes 3–4 minutes to scale up.
- Autoscaling alone won’t fix your bill. Node autoscalers provision based on what workloads request, not what they actually use. With CPU requests running ~69% above real usage, overprovisioning is built in unless you also rightsize pods.
- KEDA is the right tool for event-driven and batch workloads. It scales on queue depth, Kafka lag, Prometheus queries, and 70+ other sources – including scale-to-zero, which HPA cannot do on CPU/memory alone.
- Managed options (EKS Auto Mode, GKE Autopilot) trade control for simplicity – at a cost. EKS Auto Mode adds ~12% to EC2 on-demand prices. GKE Autopilot charges per pod resource request, which favors low-utilization workloads.
- Cast AI combines node and workload autoscaling with autonomous rightsizing. It replaces multiple tools with a single layer that provisions nodes, consolidates continuously, and adjusts pod requests – closing the gap between what’s requested and what’s actually used.
If you are evaluating cost management platforms rather than autoscaling tools specifically, see best Kubernetes cost optimization tools. This post focuses on the tools that perform scaling: node autoscalers and workload autoscalers.
How to choose: the criteria
What layer it scales, what signal it uses, how fast it reacts, what it costs to run
Four questions will narrow down your shortlist faster than any feature comparison.
What layer does it operate on? Node autoscalers (Cluster Autoscaler, Karpenter) add or remove VMs. Workload autoscalers (HPA, VPA, KEDA) change how many pod replicas run, or how many resources each pod requests. These are separate problems. Solving one does not solve the other.
What signal does it use? Both Cluster Autoscaler and Karpenter watch for pending pods. HPA watches CPU or memory utilization percentages, or custom metrics exposed through the Metrics API. VPA analyzes historical usage to recommend better resource requests. KEDA watches external event sources: queue depth, consumer group lag, Prometheus queries, and 70-plus additional scalers in the current v2.20 release.
How fast does it react? Speed matters differently depending on your workload type. For node scaling, Karpenter provisions a node in 45 to 90 seconds. Cluster Autoscaler takes 3 to 4 minutes through its ASG, MIG, or VMSS intermediary. For workload scaling, HPA checks metrics every 15 seconds and can act in under a minute. KEDA’s default polling interval is 30 seconds per scaler, configurable per ScaledObject.
What does it cost to run? All open-source tools (Cluster Autoscaler, Karpenter, HPA, VPA, KEDA) carry no licensing fee. You pay only for the nodes they provision. Managed options add overhead: EKS Auto Mode charges roughly 12% above the EC2 On-Demand price per managed node. GKE Autopilot bills per pod resource request rather than per node, which typically favors low-utilization workloads over consistently dense ones.
The comparison table
| Tool | Layer | Scaling signal | Reaction speed | Instance selection | Consolidation | Spot support | Cloud support | Managed or self-hosted | Cost model |
|---|---|---|---|---|---|---|---|---|---|
| Cluster Autoscaler | Node | Pending pods / underutilized nodes | 3-4 min scale-up; 10 min scale-down window | Pre-defined node groups only | No | Manual: separate Spot node groups required | AWS, GCP, Azure, any cloud | Self-hosted | Free; pay for nodes |
| Karpenter | Node | Pending pods (per-pod simulation) | 45-90 sec scale-up; active consolidation | Any instance type on the fly | Yes (empty, single, multi-node; SpotToSpot opt-in) | Native: automatic on-demand fallback | AWS (GA), Azure via AKS NAP (GA), GCP (no provider) | Self-hosted | Free; pay for nodes |
| EKS Auto Mode | Node | Pending pods (Karpenter engine underneath) | 45-90 sec (same as Karpenter) | AWS-managed from Karpenter pool | Yes (AWS-managed) | Yes (via NodePool capacity-type) | AWS EKS only | Managed (AWS) | ~12% surcharge on EC2 On-Demand per node, plus EC2 cost |
| GKE Autopilot | Node | Pod scheduling requests | Google-managed provisioning | Google-managed | Yes (Google-managed bin-packing) | Yes (pod annotation) | GCP GKE only | Managed (Google) | Per vCPU-hour and GiB-hour requested by running pods |
| AKS CA | Node | Unschedulable pods / underutilized nodes | 3-4 min scale-up (VMSS-backed) | Pre-defined node pools | No | Yes (Azure Spot VMSS node pools) | Azure AKS only | Semi-managed (Microsoft-integrated) | Free; pay for Azure VMs |
| HPA | Workload (replica count) | CPU/memory utilization, custom and external metrics | ~75 sec minimum under defaults; 5-min scale-down stabilization | N/A | N/A | N/A | All Kubernetes environments | Kubernetes native (built-in) | Free (built-in) |
| VPA | Workload (resource requests) | Historical resource usage (Recommender histograms) | Multi-day recommendation lag; Auto mode evicts pods to apply | N/A | N/A | N/A | All Kubernetes environments | Self-hosted (open-source) | Free (open-source) |
| KEDA | Workload (replicas, including zero) | External events: queues, Kafka lag, Prometheus, cron, 70+ scalers | 30-sec default poll; scale-to-zero on event silence | N/A | N/A | N/A | All Kubernetes environments | Self-hosted (CNCF open-source) | Free (CNCF open-source) |
Node autoscalers
Cluster Autoscaler: how it works, where it is slow, the node-group constraint
Cluster Autoscaler (v1.36.1, tracking Kubernetes 1.36) watches for pods the scheduler cannot place. When it finds one, it simulates which existing node groups could fit the pod and calls the cloud provider API for that group. Scale-up takes 3 to 4 minutes end-to-end: the call to the node group API, node registration, and pod scheduling all run in sequence.
The core constraint is structural. Cluster Autoscaler can only scale within node groups you define in advance. If your pod needs a node size that falls between two defined groups, the autoscaler picks the nearest group and wastes headroom. That headroom inflates your effective provisioning, which the autoscaler then reads as real demand on the next evaluation cycle.
Scale-down requires 10 consecutive minutes of underutilization by default, measured against resource requests rather than actual usage. Because requests typically run above real consumption, nodes that appear busy to Cluster Autoscaler are often largely idle in practice. The autoscaler also does not repack running pods; it only removes nodes that fall below its utilization threshold. For detailed tuning of scale-up and scale-down behavior, see the Kubernetes Cluster Autoscaler deep dive.
Cluster Autoscaler remains the only production option for node autoscaling on GKE Standard clusters, since no official Karpenter provider exists for GCP as of mid-2026. On AWS and Azure, Karpenter-based solutions are the recommended path for new clusters.
Karpenter: per-pod provisioning, consolidation, AWS-first
Karpenter (sigs.k8s.io/karpenter v1.8.x; karpenter-provider-aws v1.8.3) takes a fundamentally different approach to node provisioning. When a pod becomes pending, Karpenter runs a scheduling simulation directly against available instance types, selects the cheapest option that fits the pod’s resource request, and calls the EC2 API for that specific instance. It bypasses Auto Scaling Groups entirely. The result is 45 to 90 seconds from pending pod to running node, compared to the 3 to 4 minutes Cluster Autoscaler needs through its ASG, MIG, or VMSS intermediary.
Beyond speed, Karpenter actively consolidates running workloads. It handles empty-node removal, single-node consolidation (moving the last pod off an underutilized node), and multi-node consolidation (replacing several nodes with fewer, larger ones). The v1.0 release added spec.disruption.budgets to control what fraction of nodes can consolidate per cycle, which prevents the aggressive disruption that affected early adopters. One critical operational detail: PodDisruptionBudgets directly gate Karpenter’s voluntary consolidation events. If a workload’s PDB blocks eviction because maxUnavailable is already reached, consolidation stalls silently – Karpenter marks the node for draining but cannot proceed. Before enabling WhenEmptyOrUnderutilized, verify that workload PDBs allow at least one voluntary disruption, or consolidation simply will not make progress.
A minimal NodePool definition looks like this:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
limits:
cpu: 1000
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1mSpotToSpotConsolidation, which replaces an existing Spot node with a cheaper Spot node as market prices shift, is available as a feature gate but disabled by default in v1.x. Enable it with SpotToSpotConsolidation=true if Spot cost optimization is a priority. Note that Karpenter’s native Spot interruption handling requires an SQS queue and accompanying IAM provisioning; without this setup, Spot interruptions cause ungraceful pod termination rather than graceful draining – see the Karpenter interruption handling docs for the full setup. Teams planning to move from Cluster Autoscaler will find the migrating from Cluster Autoscaler to Karpenter guide useful before committing to that change. Karpenter’s main limitation is cloud coverage: AWS support is GA, Azure via AKS Node Auto Provisioning reached GA in early 2026, and no GCP provider exists yet.
Managed options: EKS Auto Mode, GKE Autopilot and node auto-provisioning, AKS cluster autoscaler
EKS Auto Mode runs Karpenter under the hood, fully managed by AWS. Provisioning speed matches self-managed Karpenter at 45 to 90 seconds. The operational trade-off is control: nodes run Bottlerocket only, SSH access is disabled, and AWS rotates nodes approximately every 21 days. Additionally, the Auto Mode NodeClass API uses eks.amazonaws.com/v1 rather than the self-managed Karpenter karpenter.k8s.aws/v1 EC2NodeClass spec. Migrating between them requires rewriting configurations, not simply pointing at a new controller.
GKE Autopilot manages node provisioning, bin-packing, and lifecycle entirely within Google’s infrastructure. It bills per pod resource request (approximately $0.0445 per vCPU-hour and $0.0049 per GiB-hour for standard compute class) rather than per node. At low or variable utilization, Autopilot typically costs less than Standard clusters: a team running at 40% node utilization on Standard paid around $832 per month for the equivalent workload that Autopilot served for roughly $380 (4 × n2-standard-4, us-central1, Standard On-Demand vs Autopilot Standard pricing, July 2026). As of 2026, Autopilot supports DaemonSets and Confidential GKE Nodes, removing two blockers that appeared in older comparisons.
GKE Node Auto-Provisioning is the Standard-mode equivalent, automatically creating node pools for pending pods that do not fit existing pools. A January 2026 update added parallel node pool creation, reducing latency for clusters that previously waited on sequential pool creation.
AKS Cluster Autoscaler integrates the upstream Cluster Autoscaler into Azure, backed by VMSS. It carries the same node-group constraints and 3 to 4 minute provisioning times as the open-source version. AKS Node Auto Provisioning, the Karpenter-based alternative, reached GA in early 2026 and is the recommended path for new AKS clusters.
What you give up for a managed autoscaler
Managed autoscalers trade operational control for reduced maintenance overhead. EKS Auto Mode adds roughly 12% to your EC2 bill per managed node and locks nodes to Bottlerocket with no host access. GKE Autopilot removes control over node placement, topology, and privileged container configurations. Both eliminate custom AMIs and OS images. For teams with strict compliance requirements, debugging needs, or specialized workloads that require host-level access, self-managed Karpenter or Cluster Autoscaler typically suits better. For teams optimizing for operational simplicity over per-node cost control, managed options deliver real value at the cost of flexibility.
Workload autoscalers
HPA: replicas on metrics
Horizontal Pod Autoscaler ships with every Kubernetes cluster and adjusts replica count based on CPU utilization, memory, or any custom metric exposed via the Metrics API. The autoscaling/v2 API, current since Kubernetes 1.23, supports multiple metrics simultaneously and lets you configure stabilization windows separately for scale-up and scale-down to prevent flapping.
A minimal HPA targeting 60% CPU utilization looks like this:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60Under default settings, HPA’s minimum reaction time is approximately 75 seconds: Metrics Server scrapes kubelet stats every 60 seconds by default, and the HPA controller runs its own sync loop every 15 seconds on top of that. Scale-up stabilization defaults to zero seconds, so HPA acts immediately once fresh metrics arrive. Scale-down waits 300 seconds by default to avoid thrashing. One hard limit: HPA cannot scale below one replica. For scale-to-zero, you need KEDA. The Kubernetes HPA guide covers tuning stabilization windows and cost implications in depth.
VPA: requests from usage, and why it conflicts with HPA
Vertical Pod Autoscaler analyzes historical resource consumption and adjusts pod CPU and memory requests to match actual usage patterns. It solves the overprovisioning problem at the workload level: pods request what they actually need rather than what an engineer estimated at deployment time. In Auto mode, VPA evicts pods to apply new requests. In Off mode, it generates recommendations without applying any changes.
VPA v1.7.0 introduces InPlace and InPlaceOrRecreate update modes, which patch the running pod via the /resize subresource rather than evicting it. These modes require Kubernetes 1.33 or later with the relevant feature gate. In Kubernetes v1.36 (April 2026), in-place pod vertical scaling graduated to Beta and is now enabled by default, so the eviction disruption problem is shrinking for clusters on newer versions.
The conflict with HPA is worth understanding before you run both tools together. When HPA and VPA both target CPU on the same workload, a feedback loop forms. CPU spikes trigger HPA to add replicas. More replicas distribute the load, so per-pod CPU drops. VPA sees lower per-pod CPU and recommends smaller requests. Smaller requests shrink the denominator HPA uses for its utilization percentage, making the same actual CPU load appear as higher utilization to HPA. HPA then adds more replicas. VPA evicts pods to apply new requests, which triggers further HPA decisions. The loop does not converge on its own.
The safe pattern: run HPA on external metrics such as request rate or queue depth, and run VPA with controlledResources: ["memory"] only. Alternatively, run VPA in Off mode to collect recommendations while HPA controls replicas independently. The HPA vs VPA post covers this conflict and the safe combination patterns in more detail.
KEDA: event-driven, scale to zero
KEDA (v2.20.2, CNCF Graduated) extends HPA to support external event sources and enables scale-to-zero. It splits autoscaling into two mechanisms: the KEDA Operator handles the zero-to-one and one-to-zero transitions by patching replica count directly; for one-to-N scaling, KEDA creates and manages a standard HPA resource automatically. Because HPA cannot go below one replica, KEDA’s Operator handles the zero edge separately from the HPA it manages.
A minimal ScaledObject targeting an SQS queue looks like this:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: sqs-processor
spec:
scaleTargetRef:
name: queue-worker
minReplicaCount: 0
maxReplicaCount: 50
triggers:
- type: aws-sqs-queue
metadata:
queueURL: https://sqs.us-east-1.amazonaws.com/123456789/my-queue
queueLength: "10"
awsRegion: us-east-1Scale-to-zero means batch jobs, queue processors, and low-traffic services stop consuming node capacity when idle. When events arrive, KEDA activates the deployment; Karpenter or Cluster Autoscaler then provisions the node underneath if needed. Cold starts are the trade-off: pods must spin up from zero on the first event. Tuning image size and readiness probes per workload keeps activation latency acceptable for most batch and async use cases.
KEDA v2.20 ships with 70-plus scalers, covering AWS SQS, Kafka consumer group lag, Azure Service Bus, RabbitMQ, Redis, Prometheus queries, Datadog metrics, and cron schedules, among others. For a deeper look at the scaler catalog and configuration patterns, see the KEDA guide.
Why autoscaling alone does not cut the bill
Autoscalers respond to requests, not usage
Node autoscalers provision against resource requests. That is by design: the Kubernetes scheduler uses requests to determine whether a pod fits on a node. However, requests and actual usage are not the same number. According to Cast AI’s 2026 State of Kubernetes Optimization Report, which covers direct telemetry from more than 23,000 production clusters before optimization was applied, CPU requests run 69% above actual CPU consumption on average. That figure rose from 40% the previous year.
The implication for autoscaling is direct. Cluster Autoscaler and Karpenter both read inflated requests as real demand. They provision capacity to meet those requests. That capacity then sits largely unused. The autoscaler did exactly what it was configured to do; the problem is upstream, in the request values that serve as its signal.
Two separate gaps exist here. The provisioning gap (69% excess capacity over what workloads request) is what node autoscalers address when you rightsize requests downward. The utilization gap (actual usage versus what workloads request) is what neither node autoscalers nor workload autoscalers close on their own without rightsizing. The Kubernetes bin-packing and node consolidation post explains how these two gaps interact at the infrastructure level.
8% CPU utilization with autoscaling switched on everywhere
The Cast AI report measures average CPU utilization at 8% (down from 10% the prior year) in clusters where autoscaling is fully enabled, with memory utilization at 20%. Those figures describe fully-autoscaled production clusters, not clusters running without scaling configured.
Pairing an autoscaler with rightsizing
Rightsizing corrects the request values that autoscalers use as their signal. When requests accurately reflect actual usage, autoscalers provision against realistic numbers. Scale-down triggers more frequently because nodes genuinely fall below the utilization threshold. Karpenter’s consolidation operates against pods that now carry accurate requests, which means fewer nodes can hold the same workload.
Cast AI’s automated rightsizing reduces provisioned CPU footprint by approximately 50% on average across production clusters once automation is in place. OOM kills drop from 40 to 50 per measurement interval to near zero in the same clusters, because memory requests converge with actual consumption instead of staying permanently overprovisioned.
Cast AI applies rightsizing in-place via Linux cgroup modification, without evicting pods. That approach works on DaemonSets as well, which VPA cannot handle. For the broader picture on pairing autoscaling with cost optimization, the guide to Kubernetes autoscaling covers the full interaction between requests, provisioning, and cost. If you want to see what rightsizing would change in your own cluster, request a demo to get a baseline analysis against your actual workload telemetry.
Which combination to run
Three worked scenarios: cost-driven, latency-driven, event-driven
Cost-driven: Your primary goal is minimizing idle node capacity and maximizing Spot coverage. Choose Karpenter (self-managed) with SpotToSpotConsolidation enabled and disruption.budgets starting at 10% (1 node per 10); tighten the budget after observing 2–3 consolidation cycles in staging. For workload scaling, run HPA on external metrics such as request rate rather than CPU, and add VPA in Off mode to collect rightsizing recommendations without disrupting replicas. Pair with automated rightsizing to ensure Karpenter consolidates against accurate requests rather than inflated ones. This combination gives you tight bin-packing without the 12% Auto Mode surcharge.
Latency-driven: Pod startup time matters more than idle cost. Here, the node provisioning delay is your ceiling. You can pre-warm capacity using pause pods (low-priority placeholder pods that keep nodes warm) so that real workloads schedule immediately when they arrive. Configure HPA with a longer scale-down stabilization window (600 to 1200 seconds) to prevent removing capacity you will need again in minutes. Use on-demand instances rather than Spot to avoid interruption risk for latency-sensitive services. If you run on GKE Standard, Cluster Autoscaler with pre-defined node pools gives predictable behavior for this scenario.
Event-driven batch: Queue processors, ML inference jobs, and data pipelines benefit from KEDA plus Karpenter on Spot. KEDA scales replicas to zero during idle periods. When events arrive, KEDA activates the deployment; Karpenter then provisions Spot capacity matched to the pod’s exact resource request. Tune KEDA’s lag threshold to your processing SLA rather than to a fixed replica count. This pattern is also the foundation for GPU inference autoscaling: KEDA reads DCGM metrics via Prometheus and scales GPU inference deployments based on actual utilization signals, while Karpenter handles GPU-aware node selection at the infrastructure layer.
GPU autoscaling is a different problem
GPU autoscaling requires a separate tool stack because Kubernetes does not expose GPU utilization through the standard Metrics API, so HPA cannot see it natively. The current pattern runs NVIDIA DCGM Exporter as a DaemonSet on GPU nodes, scrapes those metrics into Prometheus, and uses KEDA’s Prometheus scaler to drive a ScaledObject that includes scale-to-zero. Karpenter handles GPU-aware node selection at the infrastructure layer, choosing instance types with the appropriate GPU resources when pods schedule. Cast AI’s 2026 report found that average GPU utilization across clusters sits at 5%, making rightsizing and accurate scaling even more critical for GPU workloads where instance costs are high. For a full breakdown of this stack, including MIG partitioning and time-slicing trade-offs, see the dedicated GPU autoscaling post.
Conclusion
The tool choices follow directly from your workload constraints: Karpenter for AWS-first teams needing per-pod instance selection and active consolidation; Cluster Autoscaler for GKE Standard and stable workloads on any cloud; HPA for replica-based web services; KEDA when you need event-driven scaling or scale-to-zero; VPA with memory-only control when you want request accuracy without the CPU feedback loop.
Getting the tools right is necessary but not sufficient. At 69% average CPU overprovisioning, the signal every node autoscaler responds to is structurally inflated. Rightsizing corrects that signal before it reaches the autoscaler, so the capacity provisioned actually reflects real demand. The guide to Kubernetes autoscaling covers the full pairing – or request a demo to get a baseline analysis of where your cluster stands today.
Frequently Asked Questions
There is no single best Kubernetes autoscaling tool because node autoscalers and workload autoscalers solve different problems. Most clusters need one from each group. For node autoscaling on AWS, Karpenter is the current best choice for teams that want per-pod instance selection and active consolidation. Cluster Autoscaler works across all clouds and is the only production option for GKE Standard. For workload autoscaling, HPA covers most web services, KEDA handles event-driven and batch workloads with scale-to-zero, and VPA improves request accuracy. Running Karpenter plus KEDA is the recommended combination for cost-driven AWS clusters.
Cluster Autoscaler scales pre-defined node groups (ASGs on AWS, MIGs on GCP, VMSS on Azure) in response to pending pods. It takes 3 to 4 minutes to provision a new node. Karpenter bypasses node groups entirely, runs a per-pod scheduling simulation, and calls the cloud API directly for the cheapest fitting instance type. Karpenter provisions in 45 to 90 seconds and actively consolidates running workloads onto fewer nodes. Cluster Autoscaler does not consolidate. Karpenter is AWS-first (GA on Azure via AKS NAP; no GCP provider as of mid-2026). Cluster Autoscaler works across all major clouds.
Yes, but only with the right configuration. Running HPA and VPA both targeting CPU on the same workload creates a feedback loop: HPA adds replicas (reducing per-pod CPU), VPA recommends smaller requests (shrinking HPA’s denominator), and the cycle repeats without converging. The safe pattern is to run HPA on external metrics such as request rate or queue depth, and VPA with controlledResources set to memory only. Alternatively, run VPA in Off mode (recommendations only) while HPA controls replicas independently.
KEDA (Kubernetes Event-Driven Autoscaling) is a CNCF Graduated project that extends the Kubernetes HPA to support external event sources and enables scale-to-zero. It supports 70-plus scalers including AWS SQS, Kafka consumer group lag, Azure Service Bus, RabbitMQ, Redis, Prometheus queries, and cron schedules. KEDA is most useful for queue processors, batch jobs, ML inference workloads, and any service that can genuinely run zero replicas when idle. It is also the standard tool for GPU workload autoscaling via the Prometheus scaler reading DCGM metrics.
Autoscaling reduces idle capacity by scaling down when workloads are light and scaling up when demand rises. However, autoscaling alone does not fully address Kubernetes costs because node autoscalers provision against resource requests, and requests typically run 69% above actual CPU usage (Cast AI 2026 report, 23,000+ production clusters). Clusters with autoscaling fully enabled still show an average CPU utilization of only 8%. The missing piece is rightsizing: correcting request values so that autoscalers provision against realistic demand. Automated rightsizing reduces provisioned CPU footprint by approximately 50% on average in the same clusters.
EKS: self-managed Karpenter gives the most control and the lowest cost; EKS Auto Mode gives the same speed with less operational overhead but adds roughly 12% per-node surcharge. On GKE: GKE Autopilot is the simplest path and typically cheaper at low or variable utilization; GKE Standard with Cluster Autoscaler or Node Auto-Provisioning works for teams that need host access or custom node configurations. On AKS: AKS Node Auto Provisioning (Karpenter-based, GA in early 2026) is the recommended path for new clusters; AKS Cluster Autoscaler remains available for existing setups. For workload autoscaling, KEDA is natively supported on AKS, and HPA is available on all three.



