Key Takeaways
  • Overprovisioning wastes cloud spend without anyone noticing; underprovisioning causes CPU throttling, OOMKilled errors, and pods stuck in a Pending state.
  • Native VPA carries real production risk: it restarts pods to apply changes, needs roughly 8 days of usage data to size accurately, and can conflict with HPA or trigger an oversized Karpenter node purchase.
  • Zesty continuously rightsizes both pod resource requests (vertical) and minimum replica counts (horizontal) together, so the two dimensions never fight each other the way native VPA and HPA can.
  • Kubernetes’ in-place pod resize, stable as of v1.35, lets you change a running pod’s CPU and memory without restarting it, removing VPA’s biggest historical risk on clusters that support it.
  • A safe rightsizing rollout depends on guardrails (LimitRanges, resource quotas) and a staged rollout by workload risk, not on any single autoscaling tool alone.

Kubernetes pod rightsizing is the practice of setting a container’s CPU and memory requests to match what it actually uses, instead of a padded guess made once at deployment. Every team running Kubernetes ends up on one side of the same tradeoff: pay for headroom nobody uses, or risk an application crash the moment a workload needs more than it was given. Neither is really a strategy, they’re both reactions to the same underlying uncertainty about what a workload actually needs.

This guide walks through where that uncertainty comes from, why Kubernetes’ own built-in fix, the Vertical Pod Autoscaler, carries real production risk of its own, and how a newer Kubernetes feature changes the calculus entirely. It also covers a safe, staged process for rightsizing production workloads, the advanced techniques experienced platform teams use for harder cases, and how automated platforms remove the manual cycle altogether. Getting resource requests and limits right is the foundation everything else in this guide builds on, and it’s worth understanding thoroughly before touching a single running workload, since a misconfigured request or limit is one of the more common root causes of production incidents that have nothing to do with a bug in the application code itself.

What Is Kubernetes Pod Rightsizing, and Why Does It Matter?

Kubernetes pod rightsizing matters because the alternative, generous, unreviewed resource requests, creates a tension between two teams that both have a legitimate claim on the cluster. Site reliability engineers are measured on uptime, and the fastest way to prevent a crash during a traffic spike is to request more CPU and memory than a workload will realistically need. Finance sees the resulting bill and asks why the cluster is only half full.

That tension has a name worth stating plainly: engineering pads requests as insurance against downtime, and the padding shows up as underused cloud spend on someone else’s dashboard. Neither side is wrong. The SRE’s incentive is real, and so is the waste it produces.

The waste compounds at the cluster level, not just the pod level. If a workload requests 4 CPUs but only uses 0.5, the scheduler still reserves all 4 CPUs on a node, and the remaining 3.5 sit unusable by anything else. Spread across hundreds of workloads, this creates poor bin-packing: cloud servers running mostly empty while the invoice keeps climbing, because reserved-but-idle capacity looks identical to truly full capacity from a billing standpoint.

This is also why fixing rightsizing at the individual pod level only ever solves half the problem. A workload that gets its request trimmed from 4 CPUs to 1 doesn’t automatically reduce the number of nodes the cluster is running, it just means the node it’s on now has more unused room than before, unless something actively repacks workloads onto fewer, fuller nodes afterward. Pod-level rightsizing and cluster-level bin-packing are two different problems that both need solving, and a lot of rightsizing advice stops at the first one.

Resource Requests vs. Limits, and How QoS Classes Work

Kubernetes requests are the minimum CPU or memory a container is guaranteed, and the scheduler uses that number to decide which node can host the pod. Limits are the maximum a container is allowed to consume before Kubernetes intervenes to slow it down or shut it off. Getting both values right, together, is what pod rightsizing actually means.

CPU is measured in millicores, where 1000 millicores equals one full CPU core. Memory is measured in mebibytes (MiB) or gibibytes (GiB). A request of 500m CPU reserves half a core; a limit of 1000m caps the container at one full core regardless of what’s available on the node.

Kubernetes uses the relationship between a pod’s requests and limits to assign one of three Quality of Service (QoS) classes, and that class determines what happens to the pod when a node runs short on resources.

QoS ClassRequests vs. LimitsEviction Priority
GuaranteedRequest equals limit for every containerEvicted last, protected under resource pressure
BurstableAt least one request is set, but below its limitEvicted before Guaranteed, protected over BestEffort
BestEffortNo requests or limits set at allEvicted first when a node runs short

A pod with no requests or limits at all isn’t given some neutral default, it’s classified BestEffort and put first in line for eviction the moment resources get tight, whether or not that workload is actually the least important thing running on the node. This is a common, avoidable source of unexpected instability: a workload nobody meant to deprioritize ends up first on the eviction list simply because nobody set a request value for it, and the mistake usually surfaces during an incident rather than during a routine review.

The Real Cost of Getting Requests and Limits Wrong

Getting requests and limits wrong fails in two directions, and each direction has its own specific consequence. Overprovisioning wastes schedulable capacity without triggering any alert: a workload requesting far more than it uses reserves capacity that Kubernetes can’t hand to anything else, and the bill inflates without anyone noticing until someone goes looking for it.

Underprovisioning fails loudly, in three specific ways:

  • CPU throttling. A container exceeding its CPU limit gets artificially slowed down by the kernel, and users experience it as lag or slow page loads, even though nothing has technically crashed.
  • OOMKilled. A container exceeding its memory limit is terminated immediately, with Exit Code 137, and users see an error page rather than a slow one.
  • Pending pods. If a workload’s requests are too high for any single node to satisfy, the pod never starts at all, and sits in a Pending state until capacity frees up or someone intervenes.

These three failure modes are why teams default to generous requests in the first place: the cost of underprovisioning is immediate and visible, while the cost of overprovisioning is deferred and easy to miss.

How the Vertical Pod Autoscaler (VPA) Works

The Vertical Pod Autoscaler (VPA) is Kubernetes’ built-in tool for adjusting CPU and memory requests based on historical usage, and it works through three distinct components. The Recommender monitors current and historical resource consumption and calculates optimal request and limit values. The Updater checks whether running pods match the current recommendation, and evicts any pod that doesn’t. The Admission Controller intercepts pod startup, whether that’s a fresh deployment or a pod the Updater just evicted, and injects the new recommended values.

VPA can be configured into one of four operating modes. Off mode only calculates recommendations, applying nothing automatically. Initial mode applies the recommendation only when a pod is first created, never touching a running pod afterward. Recreate mode actively terminates and restarts running pods to apply new values. Auto mode is currently identical to Recreate, restarting pods to apply changes despite the different name.

Each mode trades control for automation differently, which is why choosing the wrong one for a given workload is a common source of avoidable incidents. Off mode is the only one that carries zero risk to a running workload, since nothing gets applied without a human reviewing it first, but it also means VPA is doing nothing more than generating a report. Initial mode is a reasonable middle ground for workloads that get redeployed frequently anyway, since the next deployment naturally picks up the latest recommendation without a separate restart being triggered specifically for resizing. Recreate and Auto carry the most risk and the most automation, and the distinction between them is mostly cosmetic: teams choosing Auto expecting a smarter, more cautious behavior than Recreate are working from an inaccurate assumption about what the mode actually does.

Why VPA Often Fails in Production: The Restart and Data-Lag Problems

VPA is risky in production because its two core mechanisms, how it applies changes and how it learns what values to recommend, both carry real operational cost. The restart problem is the more disruptive of the two: outside of Off and Initial mode, VPA’s Updater has to destroy and recreate a running pod to change its resources. For a stateless web server with a dozen replicas, that’s barely noticeable. For a StatefulSet, a database, or a long-running batch job, a forced restart can mean data corruption, a failed transaction, or a violated Pod Disruption Budget (PDB), the rule meant to guarantee a minimum number of healthy replicas stay online during any disruption.

The second risk is what’s often called the “8-day data problem.” VPA’s Recommender doesn’t build its recommendation from a single reading, it works from decaying histograms of historical usage, and it typically needs about 8 days of data before that recommendation reliably accounts for a full weekly traffic pattern, including whatever happens on the busiest day. Turn VPA on and apply its recommendations on day two, and there’s a real chance it hasn’t seen Friday’s traffic surge yet, meaning the recommendation underprovisions for exactly the moment a workload needs the most capacity.

Zesty avoids both of these mechanisms entirely rather than trying to work around them: it continuously re-derives and applies both pod resource requests and minimum replica counts directly from real-time usage data, independently of VPA’s restart-based Updater or its histogram warm-up period. Sizing recommendations are available within 24 hours of activation, without the multi-day wait built into VPA’s own data model.

VPA vs. HPA, and the Hidden Karpenter Cost Risk

VPA and the Horizontal Pod Autoscaler (HPA) can conflict directly when both are configured to react to the same signal on the same workload. If CPU usage spikes, HPA adds replicas to spread the load, while VPA simultaneously decides the existing pods need more CPU and restarts them to apply it. Both systems are technically doing their job, but together they produce thrashing: replicas added, pods restarted, compute wasted, and neither autoscaler settling into a stable state.

A second, less obvious risk sits one layer down, at the node level. If VPA generates a wildly inaccurate recommendation, for instance from a temporary memory leak that makes a workload look like it needs 16 CPUs, that recommendation doesn’t just fail on its own. A cluster autoscaler like Karpenter sees the resulting Pending pod, recognizes it needs a large amount of capacity, and automatically provisions an expensive instance to satisfy it. Without a cap in place, one bad VPA recommendation can multiply a monthly cloud bill overnight, and the failure is especially hard to catch quickly because everything upstream of the node provisioning decision technically worked as designed: VPA recommended a value, Kubernetes marked the pod Pending, and the autoscaler did exactly what autoscalers are supposed to do in that situation.

Zesty avoids this specific failure mode by rightsizing the vertical dimension (CPU and memory requests) and the horizontal dimension (minimum replica counts) as a single coordinated decision, rather than running two independently reacting systems against the same signal. The two dimensions are directly coordinated with each other, not routed through native VPA or HPA as separate controllers, which prevents the thrashing and the oversized-node risk described above from happening in the first place.

The Modern Fix: Kubernetes In-Place Pod Resize

Kubernetes in-place pod resize lets a running pod’s CPU and memory requests change without recreating the pod at all. Technically, it works by modifying the spec.containers[].resources values through a dedicated resize subresource, and the underlying node adjusts how much physical capacity it allocates to the container in real time, with no restart in between.

This feature reached beta status in Kubernetes v1.33 and graduated to stable in v1.35. Its arrival directly addresses the restart problem described earlier: on a cluster running a supporting version, a StatefulSet, a database, or a long-running batch job can have its resources adjusted without the downtime risk that made VPA’s Recreate and Auto modes so disruptive. Scaling resources down during quiet hours and back up for a morning traffic ramp becomes something that can happen without interrupting a single active connection, which changes the cost-benefit calculation for rightsizing entirely: teams that avoided vertical autoscaling specifically because of restart risk have a real reason to reconsider it on a cluster running a current Kubernetes version.

Zesty supports Kubernetes in-place pod resize for Kubernetes versions 1.33 and up, applying resource changes without a restart. On clusters running an older version, a resize still requires a restart regardless of which platform is managing it.

A Safe, Step-by-Step Process for Rightsizing Production Pods

Safely rightsizing Kubernetes pods in production comes down to four steps, in order: establish observability, test in recommendation mode, set guardrails, then roll out through an auditable process rather than direct edits to the running cluster.

Step 1: Establish observability before touching anything. Deploy Prometheus, Grafana, metrics-server, and kube-state-metrics, and size decisions from P95 or P99 usage rather than averages. An average hides exactly the spikes that matter; the P99 figure shows what a workload needed 99% of the time, which is the number that should actually drive a request value. Collect at least one to two full weeks of data before drawing any conclusions, since a shorter window can easily mistake a quiet stretch for the workload’s real baseline.

Step 2: Run VPA in “Off” mode first. Never let an automated tool change production on day one. Deploy VPA in Off (recommendation-only) mode against dev or staging first, and let it run for at least a full week so it captures a real weekly pattern. Review the recommendations manually before anything gets applied, and specifically check whether the recommended values line up with what the team already expects, since a recommendation that looks surprising is worth investigating before it’s trusted, not after.

Step 3: Set guardrails before automating anything. Kubernetes LimitRanges and Resource Quotas act as a namespace-level ceiling that no automated tool, however misconfigured, can exceed. Even a wildly inaccurate recommendation asking for 50 CPUs gets blocked by the quota, which is what stops the Karpenter cost-explosion scenario described earlier before it can happen. Set these guardrails before turning on any form of automation, not after the first incident makes the need for them obvious.

Step 4: Apply changes through GitOps, not direct edits. Convert every approved sizing change into a code update through a pull request, and let a tool like Argo CD or Flux apply it from there. This creates an audit trail for every change, which matters for FinOps accountability as much as for engineering trust, and turns a bad rightsizing decision into a fast revert instead of a scramble to remember what the previous value was. A change that only exists as a manual edit to the cluster, with no corresponding commit, is a change nobody can confidently undo later.

Zesty runs this process continuously, without a manual cycle: observing real usage and applying changes within configured guardrails on an ongoing basis, rather than requiring a person to re-run these four steps every time workloads shift.

Advanced Strategies: CPU Boost, KEDA, and Balloon Pods

Experienced platform teams handle three specific rightsizing problems that don’t come up in a basic setup, and each has a distinct, named technique.

The JVM/Spring Boot “CPU Boost” problem. Java and Spring Boot applications need a large amount of CPU to compile and initialize at startup, then drop to near-idle CPU usage once running. A static CPU limit set for steady-state usage throttles startup badly, adding minutes to boot time; a limit set high enough for a fast startup wastes money for the rest of the container’s life. The fix is a temporary CPU boost at startup that scales back down automatically once the application reports itself healthy.

Resolving HPA/VPA conflict with KEDA. Kubernetes Event-Driven Autoscaling (KEDA) resolves the VPA/HPA thrashing problem described earlier by giving HPA a different signal to react to. Instead of scaling replicas on the same CPU metric VPA is resizing pods against, KEDA lets HPA scale on a custom business metric instead, queue depth or active request count, for example, so the two autoscalers never compete over the same input.

Balloon pods for instant scale-ups. Cloud providers take a long time to boot a new compute instance, often several minutes, which is too slow when traffic spikes unexpectedly. Balloon pods are low-priority, BestEffort placeholder workloads that do no real work, they exist purely to reserve space on a node. When a real, high-priority workload needs to start, Kubernetes evicts the balloon pod immediately and hands that pre-warmed capacity to the workload that actually needs it.

Zesty’s approach to fast node provisioning achieves a similar effect to balloon pods without needing dummy placeholder workloads running at all: it brings real capacity online X5 faster than usual, and absorbs spikes directly, rather than reserving space that does nothing.

Recommendation-Only vs. Automated Rightsizing Platforms

Recommendation-only tools tell you where waste is; automated platforms remove it without waiting for a person to act. Open-source tools like Goldilocks, a visual dashboard built on top of native VPA, and Kubecost, strong on cost allocation with basic sizing hints layered in, both provide real visibility into where requests don’t match usage. What neither does is apply that insight, a person still has to review every recommendation and decide whether and how to act on it, which stops scaling the moment a cluster grows past a modest number of workloads.

Automated platforms close that gap by applying changes continuously, without a human in the loop for every decision. Zesty is the clearest example of what that looks like end to end: it continuously tunes pod CPU and memory requests (the vertical dimension) and continuously tunes minimum replica counts (the horizontal dimension) together, as one coordinated decision, rather than rightsizing pods alone and leaving replica counts to a separate, uncoordinated process. That combination is what actually closes the gap recommendation-only tools leave open.

CapabilityRecommendation-Only ToolsZesty
Applies changes automaticallyNo, requires manual review and actionYes, continuously
Coordinates resource requests with replica countsNo, these are handled by separate, uncoordinated toolsYes, as one coordinated decision
Works across non-production environments automaticallyManual setup per environmentAutomated across environments
Ongoing manual maintenance burdenRecurring, scales with cluster sizeMinimal, runs as a standing system

In production deployments, this combined approach has driven over 40% optimization in cluster size, including a measured 10% reduction in EKS cluster size in one case, with sizing recommendations available within 24 hours of activation and measurable savings achievable in under an hour after turning it on.

The distinction that matters most from this comparison isn’t really about accuracy, recommendation-only tools can be just as precise as an automated platform in what they recommend. It’s about what happens between the recommendation and the change actually landing in production. A tool that stops at the recommendation is only as effective as the review cadence behind it, and that cadence tends to slip the moment the team responsible for it gets pulled onto something more urgent, which is often.

Rightsizing Best Practices: Guaranteed QoS and Risk-Based Rollout Groups

The two best practices that matter most in production are protecting your most critical workloads with Guaranteed QoS, and never automating everything at once. For critical databases and payment-processing APIs, set memory requests equal to memory limits, which assigns the pod Guaranteed QoS and makes it the last thing evicted if a node runs short on resources, protecting revenue-generating systems ahead of everything else sharing that node.

Group the rest of your workloads by risk before automating anything:

  • Safe to automate first: stateless web servers, internal APIs, and redundant microservices, where a sizing misstep routes traffic to a healthy replica almost instantly.
  • Requires manual review: stateful databases, legacy monolithic services, and any workload with rare, high-memory bursts that a short observation window might miss entirely.

This grouping isn’t a one-time exercise either, new workloads need to be classified as they’re deployed, or the safe-to-automate group stops reflecting what’s actually safe without anyone updating it. A quarterly review of which workloads sit in which tier is a reasonable minimum, and any workload that’s had an incident traced back to a resource setting should be reviewed immediately rather than waiting for that scheduled check.

Automate Rightsizing With Zesty

Safe Kubernetes pod rightsizing depends on four things working together: real observability before any change, a recommendation-only test period, guardrails that cap what any tool can do, and a staged rollout that respects each workload’s actual risk, not a single autoscaling tool applied uniformly across the cluster.

Running that process by hand works for small environments, but isn’t feasible at scale. It means re-running the observability, recommendation review, and staged rollout for every workload, every time they drift, which is constantly. Zesty’s multi-dimensional autoscaling removes that manual cycle by continuously monitoring real usage and automatically tuning both pod resource requests and minimum replica counts together, the same two dimensions that cause VPA and HPA to conflict when left uncoordinated. Teams automating Kubernetes pod rightsizing this way typically see 50-80% cost savings without ever repeating the four-step process by hand.

Book a Demo with Zesty to see automated rightsizing applied against your own cluster’s usage patterns.

Frequently Asked Questions

Does resizing Kubernetes pods cause downtime?

Not necessarily. On a cluster running Kubernetes v1.33 or later, in-place pod resize can change a running pod’s CPU and memory without recreating it. On older clusters, or when using VPA’s Recreate or Auto modes, a resize still means a restart, which can be disruptive for stateful workloads regardless of which tool is managing it.

How much historical data does VPA need before its recommendations are accurate?

Can VPA and HPA be used together safely?

How does Zesty rightsize Kubernetes pods without the risks VPA carries?

How long does it take to see savings after turning on automated Kubernetes rightsizing?