Most Kubernetes bills are not expensive because the workload is heavy. They are expensive because the cluster was sized once, for the worst day of the year, and never revisited. Here is where the money actually goes, and how to get it back without risking reliability.
The core problem: requests, not usage
Kubernetes schedules pods based on their requests, not on what they actually consume. If a pod requests 2 CPU and quietly uses 0.2, the scheduler still reserves 2 CPU on that node. You pay for the reservation.
This is the single largest source of waste in most clusters, and it is invisible unless you go looking. Utilisation dashboards showing 15% cluster usage alongside nodes that cannot fit another pod is the classic signature.
Start here: compare requested CPU and memory against actual usage over a fortnight. The gap between those two numbers is your budget for improvement.
1. Right-size requests from real data
Do not guess. Measure over a period long enough to include your genuine peaks — two weeks minimum, longer if you have monthly cycles.
- Set CPU requests near the P95 of observed usage.
- Set memory requests near the observed peak. Memory behaves differently from CPU: exceeding it gets the pod killed, not throttled.
- Use Vertical Pod Autoscaler in recommendation mode to generate suggestions without applying them automatically.
On CPU limits
Setting aggressive CPU limits is a common own-goal. Once a container hits its limit it gets throttled, and latency suffers even while the node has capacity sitting idle. Many teams get better results setting sensible requests and leaving CPU limits off, while always setting memory limits.
2. Make autoscaling do the work
Three layers, and they solve different problems:
- Horizontal Pod Autoscaler — more pod replicas as load rises. Your first line.
- Cluster Autoscaler (or Karpenter) — adds and removes nodes so you are not paying for idle machines overnight.
- Vertical Pod Autoscaler — adjusts requests per pod. Useful, but do not run it on the same workloads as HPA without care; they can fight.
The saving comes from scaling down. Plenty of clusters scale up correctly and never come back down, which means you are permanently paying for your busiest hour.
3. Buy capacity properly
Compute is the bulk of most bills, and how you purchase it matters as much as how much you use.
- Spot / preemptible instances — typically 60–90% cheaper. Ideal for stateless workloads, batch jobs, CI runners and dev environments. Spread across several instance types so a single capacity crunch cannot take you out.
- Committed use discounts — commit only to the floor you are certain of. Measure your genuine baseline first; over-committing is its own expensive mistake.
- Newer instance generations — often cheaper per unit of work. ARM-based nodes can be a substantial saving where your images support them.
Reliability note: keep critical stateful components on on-demand nodes. Use PodDisruptionBudget so scale-down and spot reclamation cannot remove too many replicas of one service at once.
4. The costs nobody notices
Compute gets the attention. These quietly add up:
- Cross-zone traffic — chatty services spread across availability zones generate real charges. Topology-aware routing keeps traffic local.
- Orphaned volumes — persistent volumes outliving their pods, billed indefinitely.
- Idle load balancers — one per service adds up fast. An ingress controller consolidates them.
- Log and metric retention — full-fidelity retention for a year is rarely worth what it costs.
- Forgotten environments — staging clusters running 24/7 for a team that works eight hours a day.
5. Make cost visible, or it will drift back
Optimisation is not a one-off project. Without visibility, savings erode within months.
- Enforce namespace and label conventions so spend can be attributed to a team or product.
- Run a cost allocation tool so engineers can see the financial impact of their own workloads.
- Alert on unusual spend increases, the same way you alert on errors.
- Review quarterly. Traffic patterns change; last year’s sizing is this year’s waste.
A sensible order of work
- Measure requests against actual usage. Establish the gap.
- Right-size the ten largest workloads — usually the bulk of the saving.
- Confirm scale-down genuinely works, not just scale-up.
- Move suitable workloads to spot capacity, protected by disruption budgets.
- Clean up orphaned volumes, idle load balancers and dormant environments.
- Commit to your measured baseline only.
- Add allocation reporting so it stays fixed.
Done in that order, cutting 30–50% is a realistic outcome for a cluster that has never been reviewed — with reliability improving rather than degrading, because right-sized workloads schedule more predictably.
We do this work as part of our cloud practice — autoscaling that follows demand, and FinOps right-sizing that cuts spend without cutting uptime.