FinOps Inform
Before You Buy Savings Plans, Run EKS Cost Optimization for Engineers
Run rightsizing, enable Karpenter and Spot, fix network and storage, then buy Savings Plans. A playbook with checkpoints and an AI+expert execution option.
The single most effective way to reduce EKS spend is to follow a strict order: rightsize pod requests first, then turn on Karpenter for dynamic node provisioning and bin-packing, use Spot for anything that tolerates interruption, fix network and storage waste, and only then buy Savings Plans. Teams that follow this sequence often see compute costs drop significantly. Skip the order and you lock in waste for one to three years.
TL;DR:
- Rightsizing pod requests accurately using real workload data is essential before enabling autoscaling or purchasing Savings Plans, as misaligned requests lead to long-term waste.
- Automated node rightsize and bin-packing with Karpenter, along with Spot diversification and workload consolidation, can significantly lower compute costs once baseline requests are correct.
- Savings Plans should only be considered after the cluster is stable and workloads are right-sized, to avoid locking in unnecessary capacity and expenses.
- Network and storage waste, such as NAT Gateway charges and unattached volumes, can be quickly reduced by implementing VPC endpoints and auditing storage resources.
- Continuous visibility through detailed cost allocation tools is critical to identifying and preventing waste, ensuring sustained savings over time.
Why rightsizing pods has to come first
Rightsizing is the foundation of any credible EKS cost optimisation programme, and it's the step most teams skip because it feels less exciting than turning on an autoscaler. But every downstream lever, Karpenter's bin-packing, Spot diversification, Savings Plan sizing, works against whatever resource requests your pods currently declare. Get those wrong and you're optimising a broken baseline.
Start with real usage data, not guesswork. CloudWatch Container Insights and Prometheus both give you actual CPU and memory consumption over time, and you need at least two to three weeks of data to catch weekly traffic cycles and batch jobs that spike outside business hours.
The safe rollout looks like this:
- Deploy the Vertical Pod Autoscaler (VPA) in recommendation-only mode across your workloads.
- Compare VPA's suggested requests against your current declared requests to quantify the gap.
- Test new values in staging against performance baselines before touching production.
- Roll out changes gradually, service by service, watching for throttling or OOM kills.
- Re-run VPA recommendations monthly, since traffic patterns and code paths shift.
Freed-up headroom on over-provisioned nodes is what makes bin-packing effective in the next stage. A cluster full of pods requesting double what they use will never pack tightly, no matter how good your autoscaler is.
Pro Tip: Never let VPA auto-update production requests on day one. Run it in "Off" mode for recommendations only, validate against real load for a full billing cycle, then switch to "Auto" for lower-risk background workloads first.
How do Karpenter and bin-packing lower node costs?
Once pod requests reflect reality, node autoscaling can do its job properly. AWS's own best-practices guidance recommends optimising capacity types with autoscalers like Karpenter or Cluster Autoscaler only after rightsizing and unused-capacity reduction, precisely because sequencing matters here.
Karpenter behaves differently from the traditional Cluster Autoscaler. Instead of scaling predefined node groups, it selects instance types dynamically based on what your pending pods actually need, and it continuously evaluates whether existing nodes could be consolidated onto fewer, better-utilised instances.
- Enable Karpenter's consolidation policy so it actively repacks workloads onto fewer nodes as utilisation drops.
- Set disruption budgets carefully. Too aggressive and you risk churn during peak hours; too conservative and consolidation never triggers.
- Use Spot for non-production environments first, then extend to fault-tolerant production services once you trust the interruption handling.
- Diversify Spot requests across multiple instance families and availability zones. A single-family Spot pool is exposed to capacity shortages that a diversified one shrugs off.
- Watch for pods pinned to specific nodes via node affinity rules left over from earlier architecture decisions. They quietly block consolidation.
Pro Tip: If Karpenter's consolidation isn't reducing node count the way you expected, check for restrictive resource requests left over from before you rightsized. Old, oversized requests silently prevent bin-packing even with Karpenter running.
Combined with rightsizing, this is where the EKS Cost Optimization Handbook reports a real audit trail showing substantial reductions in monthly compute spend using a seven-step playbook: rightsizing, Karpenter, Spot, Graviton, VPC endpoints, EBS optimisation, and load balancer consolidation, in that order.
When should you buy Savings Plans?
Only after the previous two stages are stable. AWS Compute Savings Plans give meaningful discounts against on-demand pricing and cover EC2, Fargate, and Lambda under one commitment, with one or three year terms. That's exactly the problem: a three-year commitment against an unrightsized baseline locks in whatever waste currently exists in your requests.
Commit too early and you're paying a discounted rate on capacity you didn't need in the first place. The EKS Cost Optimization Handbook makes this the central lesson of its own optimisation sequence: rightsizing and autoscaling come before any purchase commitment, never after.
Before buying anything, run through this checklist:
- Have you had at least four to six weeks of stable utilisation data since rightsizing and Karpenter went live?
- Is your baseline compute footprint representative of ongoing steady-state demand, not a temporary spike or trough?
- Are cost allocation tags consistent enough that you can attribute the committed spend to specific teams or services?
- Have workloads that are naturally variable (batch jobs, seasonal traffic) been separated from the steady-state baseline you're committing against?
- Does your finance team understand the one-year versus three-year trade-off given your infrastructure's rate of change?
A one-year commitment against a stable, rightsized baseline is a low-risk way to start. Three-year terms deserve more scrutiny, especially for teams still actively re-architecting.
Cutting network and storage waste
Data transfer charges are one of the most overlooked line items on an EKS bill, and they're often the fastest to fix. NAT Gateway charges a per-GB data processing fee of around $0.045, and for any cluster with heavy traffic to S3, ECR, or DynamoDB, that adds up quickly, all traffic to those services is currently routing through NAT Gateway unless you've told it otherwise.
VPC endpoints remove that traffic from NAT Gateway billing entirely. An interface endpoint typically costs around $0.01 per hour, a fraction of what high-volume NAT processing costs at scale.
- Add gateway endpoints for S3 and DynamoDB first. They're free and eliminate NAT processing charges for that traffic immediately.
- Add an interface endpoint for ECR if your cluster pulls container images frequently, since image pulls generate significant NAT traffic.
- Migrate EBS volumes from gp2 to gp3. gp3 provides a high baseline IOPS regardless of volume size and runs roughly 20% cheaper per gigabyte than gp2, and migration happens with no downtime., and migration happens in place with no downtime.
- Audit for unattached volumes and stale snapshots. Orphaned EBS volumes from deleted pods are a quiet, recurring cost that accumulates for months if nobody's watching.
Consolidating load balancers to cut ingress costs
Every ALB you provision carries its own hourly charge plus load-balancer-capacity-unit costs which can add up significantly, and teams that spin up a dedicated ALB per service end up paying for that duplication continuously. An ingress controller changes the economics by routing many services through a single ALB using path or host-based rules.
- Audit your cluster for services each running their own dedicated ALB via annotations.
- Migrate services onto a shared ingress controller, consolidating routing rules by path or hostname.
- Keep the migration incremental, moving low-risk services first and watching for routing conflicts.
- Retain a dedicated ALB only where a service has genuinely distinct requirements, such as a separate TLS certificate chain or isolated network policy that shared ingress can't satisfy.
The savings compound quietly. Ten services on ten ALBs versus ten services on one ingress-managed ALB is a real, recurring monthly difference that shows up on every bill afterwards.
Getting visibility before you decide anything
None of the previous steps work reliably without granular visibility into where the money actually goes. Split cost allocation data (SCAD) for EKS improves Kubernetes billing visibility by attributing EC2 instance costs to individual pods.
- Opt in to SCAD in your billing preferences to start generating pod-level cost and usage records.
- Query the resulting data through Athena or visualise it in QuickSight to see cost by namespace, deployment, or team.
- Import custom labels, SCAD supports up to 50, so cost attribution maps directly onto your existing tagging strategy.
- Layer Kubecost on top for near-real-time recommendations between billing cycles, since Kubecost integrates directly with the CUR for accurate, granular allocation by namespace and pod.
| Tool | Update frequency | Primary use |
|---|---|---|
| AWS SCAD | Daily (CUR-based) | Authoritative billing-grade pod cost records |
| Kubecost | Near real-time | Day-to-day recommendations and dashboards |
| Cost Explorer | Daily | High-level trend and service-level spend tracking |
Run a cost audit at least monthly, and set alerting thresholds so anomalies surface within days, not at the end of a billing cycle when the spend has already happened.
What blocks automated savings even when the tooling is right
Plenty of teams turn on Karpenter, configure consolidation, and still see node count barely move. The usual culprit is governance, not technology.
- Overly restrictive PodDisruptionBudgets prevent Karpenter or Cluster Autoscaler from draining nodes, even when consolidation would clearly help.
do-not-disruptannotations left over from a past incident quietly pin workloads to specific nodes indefinitely.- Noisy-neighbour workloads isolated onto dedicated nodes for performance reasons create stranded capacity that never gets reclaimed.
- Untested configuration changes in production carry real risk, so validate PDB and disruption settings in staging first.
FinOps practice exists precisely to catch this gap between engineering configuration and financial outcome. A change-approval process and a shared scoreboard tying SLO health to cost trends keeps rightsizing and consolidation aligned with reliability commitments, rather than pitting the two against each other.
Pro Tip: Before assuming Karpenter "isn't working," audit every PDB and every do-not-disrupt annotation in the cluster. In most stalled consolidation cases, that's the actual blocker, not the autoscaler configuration.
The Koritsu approach: a practitioner playbook, executed for you
A leading cloud cost optimization provider follows the same sequence outlined above: visibility first, then rightsizing, then autoscaling, then network and storage cleanup, then commitments. They emphasize execution speed. Their AI agent continuously analyses cloud spend to surface exactly where money is being lost, at the pod, service, and node level, while specialists handle the actual remediation work alongside your engineering team.
That combination can shorten time-to-savings considerably compared with a DIY effort squeezed between sprint commitments. Engagement often starts with an initial assessment. Providers may take a share of the savings verified against actual billing, and teams that want ongoing protection can move onto a subscription for continuous monitoring once the initial gains are locked in.
Matching cluster scaling policy to real workload patterns
Generic autoscaling settings punish workloads that don't fit a generic pattern. A cluster running steady, predictable traffic behaves nothing like one running batch jobs at 2am and near-zero load the rest of the day, yet many teams apply identical scaling thresholds to both.
Start by separating workload classes explicitly, using node pools or Karpenter provisioners scoped to specific workload types. Batch and CI workloads belong on their own provisioner with aggressive scale-to-zero behaviour, since there's no cost justification for keeping idle capacity around between job runs. Latency-sensitive production services need a different profile: modest headroom retained at all times, with scale-up triggered on request queue depth or CPU thresholds tuned to that service's actual traffic curve, not a generic default.
Time-of-day patterns matter more than most teams account for. If your traffic reliably drops overnight, scheduled scaling (reducing minimum node counts during known low-traffic windows) captures savings that reactive autoscaling alone will miss, because reactive scaling only reacts after load has already dropped, not in anticipation of it.
Review scaling policies quarterly against actual traffic logs, not against the assumptions made when the cluster was first built. Traffic patterns shift as products evolve, and a scaling policy tuned for last year's usage curve is quietly wasting money on capacity nobody needs anymore, or worse, under-provisioning during a growth phase nobody noticed.
Managing the cost of the EKS control plane itself
The control plane charge is fixed per cluster, currently billed hourly regardless of workload size, which means the real lever isn't negotiating that fee, it's deciding how many clusters you actually need. Teams that spin up a separate cluster per environment (dev, staging, per-feature-branch, production) multiply that fixed cost needlessly when namespaces and RBAC could isolate most of those environments within fewer clusters.
Consolidate non-production environments onto shared clusters wherever workload isolation requirements allow it. A dev cluster running fifteen feature branches costs the same fixed control plane fee as one running two, so maximising utilisation of environments you're already paying for is a straightforward win.
Where regulatory or security boundaries genuinely require cluster separation, that cost is simply the price of the boundary, don't try to consolidate away compliance requirements to save on a control plane fee. But audit honestly: many multi-cluster setups exist for historical reasons rather than active isolation requirements, and those are the ones worth revisiting.
Reducing costs when running Fargate on EKS
Fargate removes node management entirely, but it also removes your ability to bin-pack workloads across shared instances, since every pod gets its own dedicated compute allocation. That trade-off means Fargate pricing punishes over-provisioned requests more directly than EC2-backed nodes do, there's no Karpenter consolidation to absorb the waste.
Rightsizing matters even more on Fargate than on EC2 nodes. Because you're billed for the vCPU and memory you request per pod, not for a shared node's total capacity, every unnecessary buffer in a pod's resource request translates directly into a larger bill with no consolidation mechanism to soften it.
Reserve Fargate for workloads where operational simplicity outweighs the cost premium, spiky, unpredictable jobs, security-sensitive workloads needing strict isolation, or teams without the capacity to manage node-level autoscaling. For steady-state, high-volume services, EC2-backed nodes with Karpenter consolidation and Spot diversification will almost always cost less once you've done the rightsizing work.
Compute Savings Plans apply to Fargate spend as well as EC2, so the same rule holds: rightsize Fargate pod requests before committing to a Savings Plan that covers Fargate usage.
Catching cost anomalies before they become a quarterly surprise
Most unexpected cost spikes trace back to something specific: a misconfigured autoscaler that scaled up and never scaled back down, a logging sidecar accidentally deployed cluster-wide, or a Spot interruption storm that triggered a fallback to expensive on-demand capacity across dozens of pods simultaneously.
Set alerting thresholds on day-over-day and week-over-week spend changes, not just absolute monthly totals. AWS Cost Anomaly Detection can flag pattern breaks automatically, and pairing it with Kubecost's namespace-level dashboards narrows the search from "the whole bill went up" to "this specific deployment did."
Build alerting around cost per unit of value where possible, cost per request served, cost per active user, rather than raw spend alone. Raw spend rising alongside proportional traffic growth isn't an anomaly. Raw spend rising while traffic stays flat is exactly the signal you want flagged immediately.
Cost impact of logging, monitoring, and other add-ons
Observability tooling is one of the most common silent cost drivers in EKS clusters, and it rarely gets audited with the same scrutiny as compute. A logging agent deployed as a DaemonSet on every node, shipping verbose debug-level logs to a managed service, can quietly rack up ingestion and storage charges that rival the compute bill it's supposed to be monitoring.
Audit log verbosity first. Most clusters ship far more log volume than anyone actually queries, and trimming debug-level logging down to warning-and-above in production often cuts ingestion costs substantially with no loss of useful signal. Second, check whether monitoring add-ons are duplicating functionality, running both a third-party APM agent and CloudWatch Container Insights simultaneously doubles collection costs for largely overlapping data.
Review add-on resource requests too. Fluent Bit, Prometheus node exporters, and service mesh sidecars all carry their own CPU and memory footprint multiplied across every node or pod they run on, and an oversized sidecar request is exactly the kind of waste rightsizing should catch but often gets overlooked because it's "just observability infrastructure," not application code.
What actually moves the needle, from someone who's seen the pattern repeat
The mistake we see most often isn't a missing tool, it's sequencing. Teams buy a three-year Savings Plan before they've rightsized, then spend the next two years locked into a discount rate on capacity they never needed. The rule of thumb worth remembering: if you haven't looked at your VPA recommendations in the last month, you're not ready to commit to anything.
The second recurring pattern is restrictive PodDisruptionBudgets quietly blocking consolidation for months before anyone notices node count hasn't moved. Check those before blaming the autoscaler. For deeper operational templates on sequencing this correctly, Koritsu AI's Kubernetes cost optimisation runbook walks through the same order in more technical detail.
How Koritsu can help you execute this without the guesswork
Reading the playbook is one thing. Executing it across a live production cluster, with real traffic, real SLOs, and real engineering time constraints, is another. Some providers combine AI agents that continuously analyse cloud spend to find exactly where the waste is hiding, with FinOps specialists who implement the fixes alongside your team, following the same sequence covered here: visibility, rightsizing, autoscaling, network and storage cleanup, then commitments.
One client, a UK bidding platform, worked with us through this exact process and cut cloud costs by 52%, a result documented in our case study. We only get paid a share of the savings we actually deliver, verified against your billing, so there's no cost to finding out what's possible. Request a free assessment and see what your cluster is actually costing you before you commit to anything else.
Sources
- AWS Compute Savings Plans pricing
- The EKS Cost Optimization Handbook: Reduce Your AWS Bill by 60% Using Karpenter and Rightsizing
- Cost optimisation compute best practices for Amazon EKS