Key Takeaways
  • A phased 30-60-90 day rollout, baseline, autoscale, automate, lowers the risk of performance regressions during optimization.
  • Static, manually-set resource requests drift out of date within weeks as workload patterns change.
  • HPA and VPA solve different problems and can create feedback loops if both are configured against the same metric.
  • CNCF research finds 70% of organizations that overspend on Kubernetes trace it back to overprovisioned resources.
  • Zesty’s Multi-Dimensional Autoscaling (MDA) continuously rightsizes pod CPU/memory requests and tunes minimum replica counts together, cutting cloud waste without manual tuning.

Introduction

Actually optimizing Kubernetes resource usage takes three things done in sequence: establish accurate baselines of real usage, implement autoscaling and bin packing to act on those baselines, then automate the process so it doesn’t decay the moment nobody’s watching. Skipping straight to autoscaling without a baseline, or automating before you understand your workload patterns, is how Kubernetes resource optimization projects stall out after one good quarter.

This isn’t another explainer on what Horizontal Pod Autoscaler (HPA) or Vertical Pod Autoscaler (VPA) do in isolation. Most engineering teams already know, at some level, that their clusters are overprovisioned. What’s missing is a sequence: a rollout plan that establishes what “right-sized” actually means for a given workload, puts automated controls in place to act on that data, and then keeps those controls current as the workload itself changes.

That sequencing matters because Kubernetes cost problems rarely come from one bad decision. They accumulate from dozens of reasonable-seeming choices made under time pressure: a resource request set generously before a launch and never corrected, a cluster autoscaler left on default settings, an HPA policy copied from another service without checking whether it fits this one’s traffic pattern. A phased framework gives teams a way to unwind that accumulation without introducing new risk at each step.

Why Manual Kubernetes Resource Optimization Fails

Manual rightsizing tends to fail in a handful of predictable ways, and most teams hit more than one at once, often without realizing the problems are connected.

Peak-theoretical sizing. Engineers set CPU and memory requests high enough to survive the worst-case traffic spike they can imagine, then never adjust those numbers once the service is stable. The result is resource requests permanently sized for an event that happens twice a year, if ever, while the cluster pays the allocation cost every hour of every day in between.

Quarterly review cycles that can’t track drift. Workload patterns shift weekly as code ships, traffic patterns change, and dependent services evolve, but manual resource reviews typically happen on a quarterly cadence at best, and often less consistently than that in real teams. By the time a review catches up, the underlying pod rightsizing assumptions it’s checking against are already stale again, which means the review is perpetually correcting for a version of the workload that no longer exists.

HPA/VPA misconfiguration on the same metric. When both a Horizontal Pod Autoscaler and a Vertical Pod Autoscaler are configured against the same metric, such as CPU utilization, they can fight each other: HPA adds replicas to relieve CPU pressure while VPA simultaneously resizes pods to relieve the same pressure, creating a scaling feedback loop that destabilizes the workload instead of correcting it. Diagnosing this kind of loop after the fact is harder than avoiding it up front, since the symptoms, flapping pod counts and inconsistent resource requests, look like several different problems at once.

DevOps-vs-dev ownership friction. Platform teams want conservative, safe resource requests that protect cluster stability. Application teams want enough headroom that their service never gets throttled or evicted under load. Without a shared, data-driven baseline, this disagreement gets resolved by whoever pushed back hardest in a meeting, not by actual usage data, which is a core Kubernetes cost optimization failure mode: the resource request that wins isn’t the accurate one, it’s the one attached to the most persistent argument.

Zesty’s Multi-Dimensional Autoscaling (MDA) continuously re-tunes both pod requests and minreplica counts to close this gap automatically, removing the manual review cycle and the ownership argument that tends to come with it.

The 30-60-90 Day Kubernetes Resource Optimization Framework

A structured Kubernetes resource optimization rollout moves through three phases, each building on the data and controls established in the one before it, rather than treating baselining, autoscaling, and automation as parallel workstreams that can be tackled in any order.

PhaseGoalKey Activities
Days 1-30Establish visibility and baselinesMeasure real CPU/memory usage at multiple percentiles, identify current waste, set KPIs
Days 31-60Implement autoscaling and bin packingConfigure HPA/VPA correctly, enable cluster autoscaling, consolidate pods onto fewer nodes
Days 61-90Automate and continuously refineReplace manual tuning with closed-loop, continuous rightsizing and replica optimization

The sequencing is deliberate. Configuring autoscaling before establishing a baseline means tuning HPA and VPA against guesses rather than real percentile data, which tends to reproduce the same peak-theoretical sizing problem the framework is meant to fix. And automating before autoscaling is correctly configured just automates whatever misconfiguration was already in place, faster.

Teams that reach Day 90 without automation typically plateau, and this is where a platform like Zesty takes over, sustaining the gains the first two phases created rather than letting them erode back toward the static, manually-set baseline the framework started from.

Days 1-30: Establish Visibility and Resource Baselines

A Kubernetes baseline period should run for at least seven to fourteen days, long enough to capture a full weekly traffic cycle including any weekend or batch-processing troughs that a shorter window would miss entirely.

During this window, capture CPU and memory usage at the 50th, 90th, 95th, and 99th percentiles, not averages. Averages hide the spikes that resource requests actually need to survive, while percentile data shows the real distribution of demand a pod experiences over time, which is the foundation for accurate pod rightsizing later in the framework. A workload that averages 30% CPU utilization but spikes to 85% at the 99th percentile needs a very different resource request than a workload that sits at a steady 30% with almost no variance, even though a naive average-based approach would size them identically.

Core KPIs to track during this baseline phase:

  • Resource request accuracy: the gap between what’s allocated and what’s actually used, tracked per pod and aggregated per namespace
  • Cost per pod and cost per namespace: a normalized figure that makes it possible to compare workloads of different sizes on equal footing
  • Pod startup time: slow startup times can indicate resource requests set too low, forcing the scheduler into retries
  • Restart frequency and Out of Memory (OOM) kill rate: a leading indicator that memory requests are undersized relative to real usage, independent of whether CPU looks fine

Tooling for this phase doesn’t need to be elaborate: the built-in metrics-server, a Prometheus and Grafana stack, or simple kubectl top checks are enough to establish a working baseline without committing to a platform decision yet. The goal at this stage isn’t perfect observability, it’s a clean, percentile-based picture of what each workload actually needs, so that Days 31-60 has real data to automate against instead of assumptions.

It’s worth resisting the urge to shorten this window under deadline pressure. A three-day sample might look clean, but it will almost certainly miss whatever caused last month’s incident review, and a baseline built on an incomplete traffic picture just relocates the peak-theoretical sizing problem from Section 1 into Days 1-30 instead of solving it. The point of the seven-to-fourteen-day window isn’t bureaucratic thoroughness, it’s making sure the percentile data Days 31-60 will act on actually reflects the workload’s real behavior, including the parts that don’t show up on a quiet Tuesday afternoon.

It also helps to baseline at the namespace level, not just the individual pod level, since cost per namespace surfaces which teams or services are driving the bulk of cluster spend, information that’s easy to lose when reviewing pod-level metrics one deployment at a time. A namespace responsible for a disproportionate share of overprovisioned capacity is usually the highest-leverage place to start Days 31-60, rather than spreading early effort evenly across every workload regardless of its actual cost footprint.

Zesty’s compute cost visibility continuously tracks these same signals without a fixed measurement window, which matters once a team moves past a one-time baseline exercise into the kind of ongoing optimization the later phases of this framework require.

Days 31-60: Implement Autoscaling and Bin Packing

Use HPA when your workload needs more or fewer replicas in response to changing load. Use VPA when individual pods are consistently over- or under-provisioned for the CPU and memory they actually use, regardless of how many replicas are running. The two solve different problems: HPA scales horizontally by adding or removing pods to match demand, while VPA scales vertically by resizing a pod’s resource requests to match its actual consumption.

The coordination risk shows up when HPA and VPA are both configured against the same metric. If VPA resizes a pod’s CPU request while HPA is simultaneously scaling replica count off CPU utilization, the two systems can compete against each other: a resize event changes the utilization percentage HPA is watching, which triggers a scaling action, which changes the aggregate utilization VPA is measuring, and so on. The result is a scaling loop that produces instability instead of the efficiency either system was configured to deliver on its own.

Cluster autoscaling adds or removes nodes based on whether existing nodes can fit pending pods, but it doesn’t decide how efficiently those pods are packed onto the nodes that already exist. That’s where Kubernetes bin packing comes in: consolidating pods onto fewer, more fully-utilized nodes so a team isn’t paying for partially-empty nodes that the cluster autoscaler has no immediate reason to remove, since technically those nodes are still hosting running pods. Kubernetes autoscaling and bin packing solve adjacent but distinct problems, and manual setups frequently address only the first, leaving fragmented, under-packed nodes as the quiet remainder of the cost problem.

ApproachHandles Pod ReplicasHandles Pod SizingHandles Bin PackingCoordination Risk
HPA aloneYesNoNoLow (single dimension)
VPA aloneNoYesNoLow (single dimension)
HPA + VPA (manual pairing)YesYesNoHigh if both target the same metric
Zesty (multi-dimensional autoscaling)Yes (min replica tuning)Yes (continuous pod rightsizing)Improve Bin Packing with Adaptive Pod PlacementLow, dimensions are coordinated together

Zesty‘s approach to multi-dimensional autoscaling coordinates min replica counts and pod sizing into a single system, rather than two separately configured tools that each optimize their own dimension without visibility into the other. Bin packing itself sits outside MDA’s scope: Zesty addresses pod-to-node consolidation through Adaptive Pod Placement (APP), a separate product built specifically to close the gaps that cluster autoscalers and manual node management leave behind, so that the replica and sizing gains MDA produces aren’t undercut by inefficient node packing elsewhere in the cluster.

This division of labor matters because bin packing is easy to overlook in a manual rollout. A team that correctly configures HPA and VPA in Days 31-60 can still be paying for a cluster full of nodes running at 30% utilization each, simply because pods landed wherever the scheduler happened to place them rather than being consolidated deliberately. Cluster autoscaling will eventually remove an empty node, but it has no mechanism to recognize that four half-empty nodes could be repacked into two fully utilized ones. Closing that gap is a distinct problem from anything HPA, VPA, or a manually-tuned cluster autoscaler is designed to solve, which is why it’s called out separately in this framework rather than folded into the autoscaling conversation.

Days 61-90: Automate and Continuously Refine

Static resource configs and quarterly manual reviews cannot keep pace with workload change that happens weekly or daily, which is precisely the gap the first sixty days of this framework exposes but doesn’t, by itself, close.

A closed-loop optimization system continuously detects pattern shifts in usage and re-tunes resource settings automatically, without waiting for a scheduled review: automation isn’t a nice-to-have layered on top of a manual process, it’s what keeps a manual process from decaying back to the static baseline it started from. That’s the principle worth carrying out of this entire framework, and it’s the reason Days 1-60 exist at all, since a closed loop is only as good as the baseline and controls it’s continuously adjusting.

At this stage, Zesty coordinates pod rightsizing and minimum replica counts together, so gains in one dimension don’t get erased by waste in the other. MDA handles both dimensions simultaneously: it vertically rightsizes pod CPU and memory requests based on real observed usage, and horizontally tunes minimum replica counts to match actual demand, working alongside native HPA and VPA rather than replacing them, so teams keep using the same native controls without exposing them to the coordination risk a manual dual setup carries. In practical terms, this means a workload’s resource requests and replica floor keep adjusting as usage patterns shift, without a platform engineer needing to notice the drift first and schedule a fix.

Published case studies show over 40% optimization in cluster size for teams that reach this automated stage, though results vary by workload composition and traffic pattern, and this figure reflects specific documented outcomes rather than a universal guarantee across every cluster. The broader point holds regardless of the exact number: the compounding effect of continuous, small adjustments tends to outperform periodic, large corrections, simply because it never lets drift accumulate long enough to become a quarterly problem again.

This is also the stage where the earlier phases start paying compounding dividends rather than one-time ones. A baseline that was accurate in Week 2 doesn’t stay accurate forever, since deployments ship, traffic patterns shift, and dependent services change their own resource footprints. Manual frameworks treat that drift as a reason to schedule another review. A closed-loop system treats it as ordinary input, something to detect and correct continuously rather than something to notice, escalate, and fix in a separate project. That distinction is the practical difference between a framework a team runs once a year and one that keeps working without anyone remembering it exists.

Teams evaluating whether they’ve reached this point can ask a simple question: if resource requests or replica floors were subtly wrong today, would anyone notice before the next scheduled review, or only after a cost report or an incident flagged it? If the honest answer is the latter, Days 61-90 haven’t actually been reached yet, regardless of how the calendar looks.

Measuring ROI: The KPIs That Prove Optimization Works

Proving Kubernetes optimization worked means comparing before-and-after data on the same metrics established in Days 1-30: utilization percentiles, restart rates, and scheduling success rate all need a clean pre/post comparison to be credible in a Kubernetes FinOps report, rather than an anecdotal sense that “things feel more efficient now.”

Tying technical metrics to a dollar figure usually comes down to a simple formula: cost per workload equals compute cost plus networking cost plus storage overhead, divided by pod count. That structure lets a platform or FinOps team translate a rightsizing win, say, a drop in average CPU request size, into a number a finance stakeholder actually cares about, without needing to understand percentile baselining or scaling feedback loops to trust the result.

KPIs worth including in an ROI report:

  • Utilization percentile shift: before vs. after, at p50/p90/p99, showing whether requests now track real usage more closely
  • Restart and OOM-kill rate change: a drop here indicates sizing improvements didn’t come at the cost of stability
  • Scheduling success rate: whether the scheduler is placing pods without retries or failures under the new configuration
  • Cost per pod and cost per namespace: the same normalized figures from the baseline phase, now showing measurable movement

Some teams see results faster than a full quarterly cycle would suggest: teams can see measurable savings within an hour of activating Zesty, which is a useful data point when justifying automation over a longer, slower manual review process to stakeholders who are used to optimization projects taking quarters rather than hours to show initial results.

Reporting this to a FinOps audience works best when the KPIs are framed as a trend line rather than a single snapshot. A one-time before-and-after comparison proves the initial rollout worked, but a monthly or quarterly trend of cost per namespace, utilization percentile, and restart rate demonstrates whether the gains are holding, which is usually the more important question for a finance stakeholder deciding whether to fund continued investment in optimization tooling. A framework that shows a strong Day 90 result but a flat or worsening trend by Day 180 has really just delayed the original overprovisioning problem rather than solved it.

Conclusion

The 30-60-90 day framework moves a team from guesswork to control in three deliberate phases: baseline real usage with percentile data rather than averages, implement HPA, VPA, cluster autoscaling, and bin packing correctly and in coordination with each other, then automate the ongoing tuning that manual processes consistently fail to sustain past the first few months.

The manual version of this framework works, in the sense that a disciplined team following it exactly as described will see real cost reductions. The problem is what it demands afterward: continuous, ongoing effort, re-baselining as workloads change, re-checking HPA and VPA configuration for drift, re-evaluating bin packing as node shapes and workload footprints shift, that most teams can sustain for a quarter but not indefinitely. Zesty automates every phase of this framework continuously, rather than as a one-time project, covering both the vertical dimension, continuous pod rightsizing based on real usage, and the horizontal dimension, continuous minimum replica tuning, coordinated with native HPA and VPA so that neither dimension’s gains get erased by drift in the other.

None of this requires abandoning the framework’s earlier phases once automation is in place. Baseline data still matters as a reference point, and HPA and VPA still do the same jobs they were configured to do in Days 31-60. What changes is who’s responsible for keeping all of it current: instead of a platform team re-running the same three phases every few months as a recurring project, a closed-loop system absorbs that responsibility permanently, freeing engineering time for work that actually requires a person’s judgment rather than a repeated measurement cycle.

If a team has already run the baseline and configured autoscaling correctly, the fastest path to further Kubernetes cost savings isn’t a bigger manual effort, it’s handing the ongoing tuning to a system built to do it continuously and without the review cycle that manual processes can’t escape. Book a Demo with Zesty to see how MDA applies this framework to your own clusters.

FAQs

What is Kubernetes resource optimization?

Kubernetes resource optimization is the practice of matching a workload’s CPU and memory requests, and its replica count, to what it actually uses rather than to a worst-case estimate set once and left alone. Done well, it reduces overprovisioned capacity without increasing the risk of throttling, restarts, or scheduling failures, and it stays accurate over time rather than drifting stale after the first review.

What's the difference between HPA and VPA, and when should I use each?

How long does it take to see cost savings from Kubernetes optimization?

How does Zesty automate Kubernetes resource optimization compared to manual tuning?

What KPIs should I track to measure Kubernetes optimization success?