When a Kubernetes bill grows faster than the business using it, the instinctive response is to look at the node fleet: fewer nodes, cheaper instance types, more aggressive autoscaling. That is rarely where the largest, easiest savings are. The waste usually lives inside the workloads themselves, in requests and limits nobody has revisited since the day they were first guessed at.

Requested resources, not used resources, drive your bill

Kubernetes schedules and bills based on what a pod requests, not what it actually consumes. A workload that requests four times the CPU it uses is paying for capacity that sits idle, and it is also preventing other workloads from being scheduled onto that same node, which pushes the cluster toward needing more nodes than it actually requires. This single gap, between requested and actually used resources, is the most common source of avoidable Kubernetes spend we see.

  • Pull actual CPU and memory usage percentiles for each workload over at least two weeks, not a single snapshot
  • Compare that against the requests currently configured, workload by workload
  • Right-size requests to a realistic percentile of actual usage, with headroom for genuine spikes, not worst-case guesswork

Namespace sprawl hides orphaned resources

Clusters that have been running for a while accumulate namespaces and workloads nobody remembers creating: a test deployment from a proof of concept, a debugging pod that was never cleaned up, an old version of a service running alongside its replacement because the decommission step got skipped. None of these show up as a single large cost, which is exactly why they persist. Together, across a large enough cluster, they add up to a meaningful, ongoing, entirely avoidable spend.

Autoscaling configuration matters more than autoscaling existence

Having the horizontal pod autoscaler and cluster autoscaler enabled is not the same as having them configured well. Scaling thresholds set too conservatively mean the cluster runs with more headroom than it needs around the clock. Scaling thresholds set too aggressively cause thrashing, where pods and nodes scale up and down repeatedly in response to normal traffic noise, which costs money in churn without actually improving responsiveness. Both failure modes are common, and both are usually invisible until someone specifically goes looking.

Storage class choices are a quiet, compounding cost

Default storage classes are often provisioned at a performance tier higher than most workloads actually need, because it is the safe, unconsidered default rather than a deliberate choice. Persistent volumes also frequently outlive the workloads that created them, continuing to bill monthly for storage nobody is reading from or writing to. A periodic review of provisioned storage against actual access patterns tends to surface savings that are easy to act on once found.

Multiple environments do not need identical resource levels

It is common, and understandable, to configure staging and development environments with resource requests copied directly from production, on the reasoning that it keeps environments consistent. Consistency in configuration and behavior does not require identical scale. A staging environment serving a handful of internal testers does not need production-level replica counts or resource requests, and the gap between those two numbers, multiplied across every non-production environment, is often a substantial, entirely safe place to cut.

Spot and preemptible instances are underused for the workloads that fit them

Not every workload can tolerate interruption, but a meaningful share of batch jobs, CI runners and stateless, horizontally scaled services can, often with very little architectural change. These workloads are strong, low-risk candidates for spot or preemptible instances, which typically cost a fraction of on-demand pricing. Teams that have not explicitly reviewed their workloads for interruption tolerance are usually leaving this savings on the table by default, not by decision.

A short audit worth running this month

  • Compare actual usage percentiles against configured requests for every workload
  • Identify and tag namespaces with no clear current owner
  • Review autoscaler thresholds for both over-provisioning and thrashing behavior
  • Audit storage classes and orphaned persistent volumes against real access patterns
  • Right-size non-production environments independently of production scale
  • Identify workloads that tolerate interruption and move them to spot or preemptible capacity

None of this requires a new platform or a FinOps tool as a first step. Most Kubernetes cost reviews we run find the majority of easy savings inside the first two items on this list, well before the conversation reaches instance types or purchasing commitments.

Does this match your situation?

Talk to BashClouds about the specifics of your setup, no obligation.

Discuss a projectMore guides