Most engineers who run Kubernetes at scale have the same VPA story. They tried it. They ran it in recommendation-only mode. They looked at what it suggested. They went "huh, that's not quite right." And they never turned it on for production. The recommendations sat in the cluster forever, ignored by the team, accomplishing nothing except occasionally generating Prometheus alerts when something fell out of sync.
This isn't a story about VPA being a bad piece of software. It's well-engineered. The team that wrote it solved a hard problem and made the code freely available. The story is about why VPA's design, the choices that made sense when it was conceived in 2018, doesn't match how production Kubernetes is operated in 2026. The mismatch is fundamental. It doesn't get fixed by a config change.
Worth walking through what's broken, because the same patterns show up in any rightsizing tool that wasn't built for modern production constraints.
What VPA does
VPA has three modes, and the differences matter.
In Off mode, VPA observes resource consumption and writes recommendations to a custom resource called VerticalPodAutoscaler. Nothing changes in the cluster. Engineers can read the recommendations and apply them manually. This is how most teams run VPA.
In Initial mode, VPA sets resource requests when pods are first created, but doesn't modify them after. Useful for batch jobs and short-lived workloads. Rarely useful for long-running services.
In Auto mode, VPA continuously adjusts resource requests by evicting pods and recreating them with the new specs. This is the mode that delivers actual savings. It's also the mode that fewer than 1% of organisations run in production.
The reason that adoption number is so low is the technical core of this post. Worth understanding each blocking issue separately.
Problem one: eviction is a production tax
To apply a resource change, VPA evicts the pod and lets the deployment controller recreate it with the new specs. There's no in-place resize. There's no rolling adjustment. The pod gets killed. A new one starts up.
For a stateless API behind a load balancer with proper readiness probes, this is mostly fine. The new pod takes a few seconds to start. Traffic shifts to other replicas. Customers don't notice. For everything else, stateful workloads, slow-startup applications, services with warm caches, anything with connection-pool state, anything customers are connected to with long-lived sessions, eviction is a real cost.
# What VPA does to apply a change to a 4-replica deployment:
# Time Action
# 00:00 Evict pod-1 (3 replicas remaining, traffic shifts)
# 00:30 pod-1 recreated with new resources (4 replicas)
# 05:00 Evict pod-2 (3 replicas remaining)
# 05:30 pod-2 recreated
# 10:00 Evict pod-3
# 10:30 pod-3 recreated
# 15:00 Evict pod-4
# 15:30 pod-4 recreated
# Total: 4 service interruptions to apply one rightsizing decision
For a workload with bursty traffic patterns or warm-up requirements (JVM applications, ML model servers, anything with significant cold-start cost), the eviction cycle erases most of the savings VPA was trying to deliver. Engineers measure this once, see the impact, and decide that automated rightsizing isn't worth it.
Kubernetes 1.27 introduced InPlacePodVerticalScaling, a feature that allows resource changes without pod recreation. It's still alpha as of mid-2026, hasn't been promoted to GA, and isn't enabled by default in any major managed Kubernetes service. VPA doesn't use it. Whenever it does become production-ready, the eviction problem will be smaller. It's not solved yet.
Problem two: the algorithm lags real traffic
VPA's recommendation algorithm uses a decaying histogram with a half-life of approximately 24 hours and an effective window of 8 days. Recent observations carry more weight than older ones, which sounds reasonable until you think about what that means in production.
Day -8 observations contribute roughly 0.4% to the recommendation. That's a problem if your most expensive workloads run on weekly or monthly cycles.
A workload with weekly business cycles, most batch processing, end-of-week reconciliation jobs, scheduled reporting, weekend traffic patterns, has its peak observed once every 7 days. With an 8-day decay window weighting recent observations heavily, that peak is dramatically underweighted in the recommendation. Result: VPA recommends sizing that's adequate for a typical Tuesday afternoon and inadequate for the workload's actual peak. Apply that recommendation and you OOM-kill during peak. Apply a recommendation that doesn't match real traffic, get an outage, never trust VPA again.
The same problem applies to monthly cycles (financial close, regulatory reporting), quarterly cycles (planning, reviews), and any workload with traffic that varies on cycles longer than a week. VPA's algorithm structurally cannot account for them.
Problem three: VPA conflicts with HPA
The Horizontal Pod Autoscaler watches a metric, typically CPU utilisation, and adds or removes replicas to keep utilisation in a target range. VPA changes the resource requests that define what utilisation means. The two interact badly.
Concrete example. HPA is configured to maintain 70% CPU utilisation across pods. Each pod requests 1 CPU. Traffic causes utilisation to climb to 80%. HPA adds replicas to bring utilisation back down. Working correctly.
Now turn on VPA. VPA observes that pods are running hot and recommends increasing the request to 1.5 CPU. The request gets bumped. Now the same actual CPU usage appears as ~53% utilisation against the new request. HPA's target is 70%. So HPA decides there's headroom and removes replicas. Now fewer pods serve the same traffic, each one runs hotter, VPA recommends another bump. The cycle continues. Either the cluster oscillates or the autoscalers fight each other into a steady state that's worse than either alone.
The official Kubernetes documentation explicitly warns against using VPA and HPA together on CPU or memory metrics. In practice, this means most teams running HPA, which is the vast majority of teams running production Kubernetes, can't enable VPA at all without breaking the autoscaler they depend on. There are workarounds (using HPA only on custom metrics, restricting VPA to specific resources), but they're brittle and add operational complexity.
Problem four: no workload awareness
VPA applies the same algorithm to every pod. A stateless API gets the same treatment as a Postgres database, the same as a Spark batch job, the same as a Redis cache, the same as a JVM application with garbage collection patterns. The histogram doesn't care.
But the right resource sizing for each of these is fundamentally different. A stateless API can be sized close to its actual usage with confidence. A Postgres database needs significant memory headroom for buffers and connection state. A JVM application needs to account for heap allocation patterns and GC overhead. A batch job needs peak-period sizing because dropping resources mid-job will fail the job.
A rightsizing algorithm that doesn't distinguish workload types will produce recommendations that work for some workloads and fail for others. The engineer reading the recommendations has to know which is which. Which means the engineer has to know more about the workloads than the algorithm does. Which means the algorithm isn't saving them work.
What better looks like
The alternative to VPA isn't a better-tuned VPA. It's an architecturally different approach that fixes the four blocking problems individually.
| Capability | Kubernetes VPA | Workload-aware AI (OptOps.ai) |
|---|---|---|
| Apply changes without disruption | Eviction required | No eviction. Changes flow through CI/CD. |
| Observation window | ~8-day decay | Weeks to months. Captures business cycles. |
| Coexist with HPA | Conflicts on CPU/memory | Compatible. Recommendations respect HPA setup. |
| Workload-type awareness | Generic algorithm | Stateful, JVM, batch, cache, distinguished. |
| Burst pattern handling | Underweighted in window | Identified and preserved as headroom. |
| Production deployment | <1% in full auto | Read-only by default. Engineering applies through CI/CD. |
| SLO awareness | None | SLO tier informs the recommendation buffer. |
VPA wasn't built for any of the constraints that matter in production. A modern alternative has to address all of them, not improve VPA at the margin.
The architectural shift is meaningful. Instead of a built-in component that observes utilisation and evicts pods, you want a system that observes the cluster from outside (read-only), learns workload behaviour over weeks (long enough to capture business cycles), produces recommendations that distinguish workload types, and integrates with engineering's existing deployment pipeline (so changes flow through CI/CD without eviction).
That's the architecture OptOps.ai is built around. The AI observes the cluster continuously, learns the burst patterns, batch cycles, and SLO tiers of each workload, and produces sized recommendations engineers can review and apply through Terraform, Karpenter, or whatever deployment tooling the team already uses. No eviction. No HPA conflict. No 8-day window. The recommendations get materially better as the AI observes more business cycles.
When VPA is still the right choice
One honest note before closing: VPA in Off mode (recommendation-only) on stateless dev or staging workloads is a perfectly reasonable use case. If you have a low-criticality cluster running short-lived stateless services, want a free signal about resource sizing, and can implement recommendations manually when they look right, VPA does that job fine.
The argument isn't that VPA is bad. The argument is that VPA isn't sufficient for production rightsizing in environments where the four blocking problems matter. Which is most production environments.
If you're running stateless workloads in dev/staging and want a free utilisation signal: VPA in Off mode is fine. If you're trying to rightsize production workloads with weekly or longer business cycles, HPA on CPU/memory, or any meaningful operational risk from eviction: VPA is the wrong tool. Look at workload-aware alternatives that don't carry the architectural baggage.

