Key Takeaways
  • Most EKS compute spend is wasted at the request layer, where clusters typically use only 10-25% of requested CPU.
  • Cost levers must be applied in order: rightsize requests first, reclaim node capacity second, change capacity types third.
  • Autoscaling layers conflict by default, and uncoordinated HPA, VPA, and Karpenter configurations can erase the savings they were meant to create.
  • Spot, Savings Plans, and On-Demand are a portfolio decision, not an either/or choice.
  • Zesty automates pod rightsizing, node consolidation, and commitment coverage together, cutting Kubernetes compute costs by 50-80%.

EKS cost optimization is a return-on-effort problem before it’s anything else: five levers exist, each with a different payoff, a different cost, and a different failure mode if applied out of order. Most guidance treats them as a checklist. This one ranks them, sequences them, and tells you what breaks when you skip ahead. Compute, specifically the EC2 worker nodes backing your pods, dominates the EKS bill, and the levers below are ordered by return so you spend effort on the highest-payoff work first.

Where EKS Compute Spend Actually Goes

EKS costs come from five components: EC2 worker nodes, which dominate the bill; a fixed control plane fee; Fargate pods, if used; data transfer; and attached storage. Compute is where the leverage is, and it fails in two structurally distinct ways that require separate fixes.

The first is waste at the request layer: pods reserving CPU and memory they never use, which Kubernetes still schedules against and which you’re still billed for through the node capacity backing it. The second is waste at the node layer: provisioned instances sitting there with no pod using the capacity, a separate problem from request accuracy entirely. A cluster can have perfectly accurate requests and still waste money on fragmented nodes, or perfectly consolidated nodes and still waste money on padded requests. Fixing only one layer stalls out fast.

Waste TypeWhat It Looks LikeTypical MagnitudeFix Layer
Request-layer wastePods requesting 2-4x their actual p95 usage20-40% of compute spendLayer 1: Rightsizing
Node-layer wasteProvisioned capacity no pod can be scheduled onto15-30% of compute spendLayer 2: Bin packing/consolidation

Platforms like Zesty that measure both layers of waste continuously close the gap that a cost dashboard alone leaves open: knowing the two numbers exist is not the same as knowing which one is costing you more this month.

The EKS Compute Savings Stack: Five Layers Ranked by Return

The ordering principle behind this entire stack is simple to state and easy to violate: never buy discounts on capacity you shouldn’t be running in the first place. Rightsizing and consolidation shrink the baseline; capacity type and commitments then discount that smaller baseline. Reverse the order and you’re paying a great rate for waste you were about to eliminate.

LayerLeverTypical SavingsEffortRiskTime to Value
1Rightsize requests20-40%MediumLow, if done from percentiles2-4 weeks
2Reclaim node capacity15-30%MediumMedium, without PDBs in place2-4 weeks
3Capacity-type portfolioUp to 90% on shifted workloadsMediumMedium to high, without diversificationDays to value
4Commitment coverage20-40% on steady-stateLowHigh, if bought before optimizing1-3 months to fully realize
5Architecture efficiency~20% on shifted workloadsHigh (build changes)Low4-8 weeks

Zesty runs layers one through four as a single automated system rather than four separate manual workstreams, which is exactly what enables teams to maintain their savings continuously throughout the year, instead of having each reduction expire the following month.

Layer 1: Rightsize Requests Before You Touch Anything Else

Requests, not usage, determine what you pay for: Kubernetes schedules against the request value, so a pod requesting 4 vCPU and using 1 reserves the other 3 regardless of what’s actually running. Per-container requests matter too, since sidecars need their own accurate sizing, not just the main application container.

Rightsizing decays for four structural reasons:

  • CI/CD deployments change resource behavior with every release, so a request tuned for last month’s build may not fit this month’s.
  • Traffic seasonality shifts the real requirement within weeks, especially for anything with a weekly or seasonal pattern.
  • Dependency changes alter memory and CPU footprints silently from the application’s perspective, even when nobody touches the deployment manifest.
  • Rightsizing decisions are based on a week or two of usage data, and that data stops reflecting reality the moment traffic patterns or deployments shift again.

The tooling landscape here has a real gap, and it’s a gap in application, not analysis. Goldilocks, Robusta KRR, and the Vertical Pod Autoscaler (VPA) all analyze usage and produce recommendations, but AWS itself recommends running VPA in recommendation-only mode rather than applying changes automatically. That leaves most teams applying VPA’s recommendations by hand, quarter by quarter, drifting again the moment the next release ships. Zesty’s Multi-Dimensional Autoscaling (MDA) closes that gap directly, continuously re-deriving and applying pod-level rightsizing decisions on its own instead of leaving them in a dashboard for someone to act on.

Layer 2: Reclaim Idle Node Capacity With Bin Packing and Consolidation

Kubernetes bin packing is the practice of scheduling more workloads onto fewer, better-sized nodes, and the arithmetic is blunt: ten nodes running at 60% utilization each are paying for ten nodes while using the equivalent of six. That’s 40% of provisioned capacity sitting idle, and it doesn’t show up in a per-pod cost report at all.

Cluster Autoscaler (CA) scales pre-defined node groups and can’t reduce capacity below an Auto Scaling group’s (ASG) configured minimum, with scale-down governed by two defaults: a 50% utilization threshold and a 10-minute unneeded-time window before a node is even considered for removal. Karpenter provisions instances without pre-defined groups and consolidates continuously through Karpenter consolidation, actively looking for opportunities to repack pods and terminate emptied nodes rather than waiting on a fixed schedule. The Kubernetes descheduler serves a similar role on the CA side, repacking on its own schedule instead of reacting to consolidation events.

Cluster AutoscalerKarpenter
Provisioning modelPre-defined node groups, fixed instance typesGroupless, provisions any fitting instance type
ConsolidationManual thresholds, slower to reactContinuous, built in
Configuration overheadHigher, requires managing multiple node groupsLower, single NodePool spec
Scale-down behaviorUtilization threshold plus unneeded-time delayConsolidates as soon as a better fit exists

Tighter packing isn’t free: it means more scale-up events, and cold node provisioning adds real latency during scaling spikes, a trade-off flat best-practice guides tend to skip over. The two most common blockers to scale-down are over-restrictive PodDisruptionBudgets, which prevent enough pods from being evicted at once to fully drain a node, and pods annotated as unsafe to evict left in place long after the reason for that annotation is gone. Zesty’s Adaptive Pod Placement (APP) continuously repacks workloads within PodDisruptionBudget limits instead of waiting for a scheduled consolidation pass, closing those two blockers without a human auditing PDBs and eviction annotations by hand. 

On the scale-up side, Zesty’s FastScaler addresses the cold-start latency directly: hibernated node pools with preloaded container images bring new capacity online up to 5x faster than a cold boot, so tighter packing doesn’t trade savings for a slow response to a spike.

Layer 3: Build a Capacity-Type Portfolio: Spot, On-Demand, and Fargate

This is portfolio construction, not a single choice between capacity types. EKS Spot Instances offer discounts up to 90% off on-demand pricing, but come with a two-minute interruption notice, which makes them a fit for interruption-tolerant, fast-starting workloads and requires wide instance-type diversification to avoid correlated reclaims. On-Demand carries no commitment and no interruption risk at the highest unit price, which is exactly why it belongs on the unpredictable top of your capacity curve rather than the stable floor.

Fargate vs EC2 comes down to a trade-off, not a verdict: Fargate needs no instance management, but each pod gets its own node-equivalent, forfeiting bin packing entirely and rounding pod sizes up to fixed configurations, so a workload needing 1 vCPU and 0.5 GB of memory is billed as 1 vCPU and 2 GB.

Capacity TypeDiscount vs On-DemandInterruption RiskManagement OverheadBest-Fit Workload
SpotUp to 90%2-minute noticeRequires instance-type diversificationStateless, fault-tolerant, batch
On-DemandNoneNoneNoneUnpredictable, low interruption tolerance
FargateVaries, no bin packingNoneLowest, no node managementSimple workloads, no ops overhead wanted

The allocation heuristic that keeps this simple: commitments cover the floor, Spot covers interruption-tolerant variable load above it, and On-Demand absorbs whatever’s left. Zesty’s AWS Commitment Optimization keeps that floor coverage matched to your actual steady-state baseline as the portfolio shifts, so the commitment layer of this mix doesn’t need a manual review every time the Spot and On-Demand split changes.

Layer 4: Cover Your Baseline With Commitments, Without the Lock-In Trap

Compute Savings Plans discount up to 66% and apply flexibly across instance family, region, and even Lambda and Fargate usage. EC2 Instance Savings Plans discount up to 72% but lock coverage to a specific instance family and region. Enterprise Discount Program (EDP) agreements exist for larger, negotiated commitments at scale.

InstrumentDiscountFlexibility
Compute Savings PlansUp to 66%Flexible across instance family, region, Lambda, Fargate
EC2 Instance Savings PlansUp to 72%Locked to instance family and region

Should you buy Savings Plans before or after rightsizing? After, without exception. A one- or three-year commitment sized before you optimize locks in your current waste as a fixed obligation, and the same optimization work that’s supposed to cut your bill ends up stranding coverage you already paid for. The fix is sequencing: optimize first, commit to the post-optimization floor, and reassess coverage as that floor moves. Zesty’s commitment optimization sizes coverage against your optimized baseline, not your current waste, through daily-adjusting coverage rather than a one-time long-term commitment purchase.

Layer 5: Architecture-Level Efficiency: Graviton, GPUs, and Accelerators

Graviton (arm64) processors run roughly 20% cheaper and about 60% more energy-efficient than comparable x86 instances, the single cheapest lever on this list per unit of engineering effort, though it requires multi-architecture container builds to use. EKS supports mixed-architecture clusters, and Karpenter can allow both arm64 and amd64 in a single node pool while keeping any given workload pinned to one architecture for predictable performance.

GPU-bound machine learning workloads are usually underutilized rather than undersized, meaning the fix isn’t more GPUs, it’s better GPU utilization on the ones already running. Time-slicing and Multi-Instance GPU (MIG) both raise utilization per device instead of adding hardware, which is the accelerator equivalent of bin packing.

Why Your Autoscaling Layers Fight Each Other

Best-practice lists rarely mention this: the autoscaling layers above don’t coordinate with each other by default, and that’s a structural problem, not a misconfiguration.

  1. HPA and VPA both reacting to CPU on the same workload produce oscillation. VPA raises requests based on observed CPU, HPA adds replicas based on the same signal, and each controller’s action changes the input the other one is watching. Mitigation: keep VPA and HPA on different metrics for the same workload, never the same one.
  2. Aggressive node consolidation collides with restrictive PodDisruptionBudgets. A node can look eligible for removal while a PDB blocks the eviction that would actually empty it, so the node stays up, fully billed, indefinitely. Mitigation: audit PDBs specifically for the workloads you expect consolidation to target, before enabling it more broadly.
  3. Tight bin packing plus deep Spot usage compounds risk. A reclaim event on a densely packed node evicts many pods simultaneously instead of one or two, since bin packing maximized how much was running on that exact node. Mitigation: cap Spot density on your most tightly packed nodes, or diversify instance types enough that a single reclaim doesn’t concentrate impact.

These conflicts are structural because each controller optimizes one dimension in isolation, with no shared view of what the others are doing to the same cluster at the same time. Zesty coordinates pod and node scaling in one control loop, which is what removes the feedback loops entirely instead of asking each autoscaler to guess what the others just did.

The 90-Day EKS Cost Optimization Sequence

PhaseDaysActionsExpected Cumulative SavingsPrimary Risk
11-14Instrument and baseline: cost per namespace, requested vs. used CPU/memory, node utilization distribution0% (measurement only)Skipping baseline and losing the ability to prove savings later
215-30Rightsize the top 20 workloads by requested capacity, staging first15-25%Cutting from averages instead of percentiles
331-45Enable node consolidation, tune scale-down thresholds25-40%Consolidating without verified PDBs in place
446-60Introduce Spot for interruption-tolerant workloads, diversified instance types35-55%Insufficient instance-type diversity concentrating reclaim risk
561-75Measure the new steady-state floor35-55% (no new savings, verification phase)Measuring too early, before the floor has actually stabilized
676-90Purchase commitments against that floor, set a quarterly review cadence50-70%+Committing against a floor that’s still moving

Every phase in this table has to repeat as the cluster changes, which is exactly why teams running Zesty compress this 90-day sequence into a single onboarding rather than a recurring quarterly project.

Verify It Worked: Four Metrics That Prove Savings Landed

Optimization without measurement is a guess wearing a dashboard. Four metrics settle the question:

  1. Request efficiency (used ÷ requested CPU and memory). Healthy range: 60-80%. Below 40% means requests are still padded well past actual usage.
  2. Node utilization (requested ÷ provisioned capacity). Healthy range: 70-85%. Below 50% means fragmentation is eating the consolidation gains you should have from Layer 2.
  3. Cost per unit of work (cost per thousand requests, per job, or an equivalent business-output metric). This is the one that separates real efficiency gains from a quiet drop in traffic that just looks like savings.
  4. Commitment utilization and coverage. Healthy range: 85%+ utilized. Low utilization means you bought coverage against a baseline that’s since moved.

None of this works without a tagging prerequisite: worker nodes need AWS resource tags for costs to appear correctly in Cost Explorer, and Kubernetes labels don’t map to AWS tags automatically, so pod- and namespace-level allocation needs Kubernetes-aware cost tooling to close that gap. Zesty’s Compute Cost Visibility ties spend back to namespaces and workloads directly, which is what makes these four numbers trustworthy without a separate tagging project first.

Conclusion: Run the Whole Stack Automatically

The stack in order: rightsize requests, reclaim node capacity, build a capacity-type portfolio, cover the baseline with commitments, then push architecture-level efficiency, each layer discounting a smaller, more accurate version of the one before it. Every layer in that stack decays: requests drift with each deployment, the optimal instance mix shifts with traffic, Spot availability changes, and the commitment floor moves every time you optimize again. Manual execution means quarterly reviews that are already stale by the time they ship, plus recurring friction between platform teams and the application owners whose requests just got cut.

Zesty automates the full savings stack:

  • Multi-Dimensional Autoscaling (MDA) rightsizes pods continuously, applying decisions on its own instead of leaving them in a dashboard for someone to act on periodically.
  • Adaptive Pod Placement (APP) consolidates nodes continuously within Pod Disruption Budget limits, closing the fragmentation gap Karpenter and Cluster Autoscaler leave open on their own
  • AWS Commitment Optimization sizes Savings Plan coverage against your actual, current baseline instead of a purchase made months before it moved
  • Compute Cost Visibility ties every one of those numbers back to the namespace and workload that owns it

Together, that’s 50-80% Kubernetes compute cost reduction with no per-workload manual tuning behind it.

Book a Demo with Zesty to see which layer of this stack is costing you the most right now.

FAQs

What is the fastest way to reduce EKS costs?

Rightsizing requests, since it’s the highest-return, lowest-risk lever on the stack and typically delivers 20-40% on its own within weeks. Node consolidation is the next fastest, but only after rightsizing shrinks the baseline it’s consolidating.

Should I use Karpenter or Cluster Autoscaler for cost optimization?

Is it safe to run production workloads on Spot instances in EKS?

How does Zesty reduce EKS compute costs compared to configuring HPA, VPA, and Karpenter manually?

Should I buy AWS Savings Plans before or after rightsizing my EKS workloads?