{"id":68,"date":"2026-10-14T07:27:06","date_gmt":"2026-10-14T07:27:06","guid":{"rendered":"https:\/\/smartcloudspend.com\/?p=68"},"modified":"2026-10-30T11:59:23","modified_gmt":"2026-10-30T11:59:23","slug":"kubernetes-finops-over-provisioned-pods-cpu-limits","status":"publish","type":"post","link":"https:\/\/smartcloudspend.com\/?p=68","title":{"rendered":"Preventing Cloud Waste Caused by Over-Provisioned Pods and CPU Limits"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>By Ra\u00fal P\u00e9rez \u00b7<\/em> <em>Last updated: October 2026 \u00b7 Reading time: 14 min<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is a pattern that plays out in almost every Kubernetes organization. A team deploys a service, copies a resource block from another manifest, and writes <code>cpu: 2<\/code> and <code>memory: 4Gi<\/code> &#8220;to be safe.&#8221; The service happily runs on a fraction of that. Nobody notices, because nothing breaks. Multiply that habit by hundreds of workloads, and the cluster ends up paying for a large amount of capacity that no process ever touches.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The other half of the story is just as expensive in a different way. CPU <strong>limits<\/strong> set too low throttle applications and slow down requests. Teams react by raising limits, and requests along with them, which pushes the cluster to add more nodes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide explains exactly how over-provisioned pods and CPU limits create waste, how to measure both problems with real queries, and how to fix them safely without causing incidents.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Requests and Limits: The Two Numbers That Drive Your Bill<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every container can declare two resource values:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Requests:<\/strong> the amount the scheduler <em>reserves<\/em> for the container. The pod is only placed on a node with enough unreserved capacity.<\/li>\n\n\n\n<li><strong>Limits:<\/strong> the maximum the container may consume at runtime.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>resources:\n  requests:\n    cpu: 500m\n    memory: 1Gi\n  limits:\n    cpu: \"1\"\n    memory: 1Gi<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The cost implication is the key insight: <strong>you pay for nodes, and nodes are sized to satisfy requests<\/strong>. A pod that requests 2 CPUs but uses 0.2 still occupies 2 CPUs of schedulable capacity. Nothing else can use that reserved space, even though it is idle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is why the gap between requested and used resources is the most direct measure of Kubernetes waste.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Over-Provisioning Creates Waste<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Inflated requests strand node capacity<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine a node with 8 vCPUs. If four pods each request 2 vCPUs but average 0.3 vCPU in real use, the node is <em>full<\/em> from the scheduler&#8217;s perspective while sitting at about 15 percent CPU utilization. The autoscaler adds another node for the next pod. You are paying for two nodes to do the work of one.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Poor bin packing and fragmentation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Large, round-number requests make packing harder. A node with 3 free CPUs and 8 GB of memory free cannot host a pod requesting 4 CPUs. Capacity is left behind in fragments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Replicas multiply the mistake<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A 1 CPU over-request on a deployment with 30 replicas is 30 CPUs of waste. Autoscalers based on request utilization (such as HPA with percentage targets) can also behave strangely when the baseline is inflated, because utilization looks permanently low and the deployment never scales as designed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Memory over-provisioning is just as costly<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Memory is typically the resource that determines node type. Over-requesting it forces you onto larger or more memory-optimized instances, which cost more per vCPU.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. The &#8220;set it and forget it&#8221; effect<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Requests are usually written once, at launch. Traffic patterns, code and dependencies change, but the numbers do not. A request sized for a launch spike can remain for years.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why CPU Limits Often Make Things Worse<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CPU limits are one of the most debated topics in Kubernetes performance. To understand why, you need to know how they are enforced.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How CPU limits work<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">CPU is a <em>compressible<\/em> resource. When a container hits its limit, Kubernetes does not kill it. Instead, the Linux kernel&#8217;s CFS (Completely Fair Scheduler) quota mechanism <strong>throttles<\/strong> it: the container is paused for the remainder of the current scheduling period (100 ms by default) once it has used its quota.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That means a container with a limit of 1 CPU can be throttled even when the node has plenty of idle CPU. For latency-sensitive applications, throttling shows up as unexplained tail latency, slow health checks and timeouts.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The expensive feedback loop<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here is how this turns into cloud waste:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>A service is given a low CPU limit.<\/li>\n\n\n\n<li>It gets throttled during bursts, and latency rises.<\/li>\n\n\n\n<li>Engineers respond by increasing the limit, and often the request too.<\/li>\n\n\n\n<li>Requests are now inflated, nodes are underused, and the autoscaler adds capacity.<\/li>\n\n\n\n<li>Cost goes up, and the original cause (a limit that is too tight for bursty workloads) was never properly diagnosed.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Detect throttling with metrics<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The fraction of CPU periods in which a container was throttled is the best indicator:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Percentage of CPU periods throttled, per container, over 5 minutes\nsum by (namespace, pod, container) (\n  increase(container_cpu_cfs_throttled_periods_total{container!=\"\"}&#91;5m])\n)\n\/\nsum by (namespace, pod, container) (\n  increase(container_cpu_cfs_periods_total{container!=\"\"}&#91;5m])\n) * 100<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As a rough guide, sustained throttling above 5 to 10 percent for a latency-sensitive service deserves investigation. Also correlate with application latency (p95 and p99) rather than looking at throttling in isolation. Some batch workloads tolerate throttling without any user-visible effect.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">So, should you remove CPU limits?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There is no universal answer, but a commonly recommended pattern is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Always set CPU requests.<\/strong> They determine scheduling and give the container a guaranteed share under contention.<\/li>\n\n\n\n<li><strong>Always set memory limits, equal to memory requests.<\/strong> Memory is not compressible: exceeding it causes OOM kills, and equal values give predictable behaviour.<\/li>\n\n\n\n<li><strong>Consider omitting CPU limits<\/strong> for latency-sensitive, trusted workloads, so they can use spare node CPU instead of being throttled.<\/li>\n\n\n\n<li><strong>Keep CPU limits<\/strong> where you need strict multi-tenant isolation, run untrusted workloads, want predictable performance in benchmarks, or must meet compliance rules. Also use them in namespaces with a LimitRange or policy that requires them.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># Typical pattern for a latency-sensitive API\nresources:\n  requests:\n    cpu: 400m\n    memory: 768Mi\n  limits:\n    memory: 768Mi     # no CPU limit<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Note the interaction with QoS classes: a pod with requests equal to limits for both CPU and memory is <strong>Guaranteed<\/strong>; a pod with requests lower than limits (or no limits) is <strong>Burstable<\/strong>; a pod with neither is <strong>BestEffort<\/strong> and is evicted first. Removing the CPU limit moves a pod from Guaranteed to Burstable, which affects eviction order under node pressure. Weigh that for critical workloads. Also, if you use the static CPU manager policy for pinned cores, you need Guaranteed pods with integer CPU values.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Measure the Waste<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You cannot fix what you have not quantified. Use these approaches in order of effort.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Quick check with kubectl<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># What pods are actually using right now (needs metrics-server)\nkubectl top pods -A --containers --sort-by=cpu\n\n# What they requested\nkubectl get pods -A -o custom-columns=\\\nNS:.metadata.namespace,POD:.metadata.name,\\\nCPU_REQ:.spec.containers&#91;*].resources.requests.cpu,\\\nMEM_REQ:.spec.containers&#91;*].resources.requests.memory<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A point-in-time view is only a rough guide. Real sizing needs history.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">PromQL for requested vs used CPU<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># CPU request efficiency per namespace over 7 days (1.0 = perfect)\nsum by (namespace) (\n  avg_over_time(rate(container_cpu_usage_seconds_total{container!=\"\"}&#91;5m])&#91;7d:5m])\n)\n\/\nsum by (namespace) (\n  avg_over_time(kube_pod_container_resource_requests{resource=\"cpu\"}&#91;7d])\n)<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code># Memory request efficiency per namespace (working set vs requests)\nsum by (namespace) (\n  avg_over_time(container_memory_working_set_bytes{container!=\"\"}&#91;7d])\n)\n\/\nsum by (namespace) (\n  avg_over_time(kube_pod_container_resource_requests{resource=\"memory\"}&#91;7d])\n)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A ratio below roughly 0.3 over a representative period is a strong sign of over-provisioning. Cost tools such as OpenCost and Kubecost present the same data as an efficiency percentage and convert the gap into dollars. See [How to Use Kubecost to Track Namespace Spending in Real Time].<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Rank by dollar impact<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Do not start with the 5,000 smallest workloads. Rank by <code>(requested - used) * unit price * replicas<\/code> and attack the top 20. In most clusters, a small number of deployments account for most of the waste.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Choose a Right-Sizing Method<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Option A: Percentile-based manual sizing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Collect at least one to two weeks of data (include month-end or other known peaks) and set:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CPU request:<\/strong> around the 90th to 95th percentile of observed usage, plus 10 to 20 percent headroom.<\/li>\n\n\n\n<li><strong>Memory request and limit:<\/strong> the peak working set over the period plus 15 to 25 percent headroom, because memory spikes are less forgiving.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code># p95 CPU usage over 14 days\nquantile_over_time(0.95,\n  rate(container_cpu_usage_seconds_total{namespace=\"payments\",container=\"checkout-api\"}&#91;5m])&#91;14d:5m])\n\n# max memory working set over 14 days\nmax_over_time(\n  container_memory_working_set_bytes{namespace=\"payments\",container=\"checkout-api\"}&#91;14d])<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Worked example (illustrative numbers): a container requests 2000m CPU and 4Gi memory. Over 14 days its p95 CPU is 350m and its peak memory is 1.1Gi. A reasonable new setting is 450m CPU and 1.4Gi memory. That is about a 77 percent reduction in CPU requests and 65 percent in memory requests for that container, multiplied by every replica.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Option B: Vertical Pod Autoscaler (VPA)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">VPA watches usage and recommends requests. Start in recommendation-only mode:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: autoscaling.k8s.io\/v1\nkind: VerticalPodAutoscaler\nmetadata:\n  name: checkout-api\nspec:\n  targetRef:\n    apiVersion: apps\/v1\n    kind: Deployment\n    name: checkout-api\n  updatePolicy:\n    updateMode: \"Off\"\n  resourcePolicy:\n    containerPolicies:\n    - containerName: \"*\"\n      minAllowed:\n        cpu: 50m\n        memory: 64Mi\n      maxAllowed:\n        cpu: \"2\"\n        memory: 4Gi<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl describe vpa checkout-api   # see Lower Bound, Target, Upper Bound<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Use the <strong>Target<\/strong> as a starting point and the <strong>Upper Bound<\/strong> as a sanity check for peaks. Do not run VPA in automatic mode against the same CPU or memory metric that an HPA scales on, since they will conflict. Newer Kubernetes releases are adding in-place pod resource resizing, which reduces the need to restart pods when requests change. Check what your version supports.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tools such as Goldilocks give a dashboard of VPA recommendations per namespace, which is useful for teams that prefer a visual workflow.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Option C: Commercial or managed rightsizing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Kubecost, Cast AI and other platforms offer automated recommendations and, in some cases, automatic application of right-sizing. These can save engineering time, but treat any automation carefully and start in dry-run mode.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Roll Out Changes Safely<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Cutting requests is the most common cause of self-inflicted incidents, so manage the risk.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Start with non-production<\/strong> and with stateless services.<\/li>\n\n\n\n<li><strong>Change one workload at a time<\/strong> and watch p95 latency, error rate, restarts and OOM kills for several days.<\/li>\n\n\n\n<li><strong>Reduce in steps.<\/strong> Cut by about half the gap first, then re-measure, rather than jumping to the final value.<\/li>\n\n\n\n<li><strong>Keep memory headroom.<\/strong> An OOM kill is a visible failure, while excess memory is just money.<\/li>\n\n\n\n<li><strong>Use PodDisruptionBudgets and rolling updates<\/strong> so a bad sizing does not take the service down.<\/li>\n\n\n\n<li><strong>Define a rollback.<\/strong> Keep the previous manifest in version control and use GitOps so reverting is a single commit.<\/li>\n\n\n\n<li><strong>Record before and after cost<\/strong> so savings are visible to leadership.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Watch for these warning signals after a change:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># OOM kills\nincrease(kube_pod_container_status_last_terminated_reason{reason=\"OOMKilled\"}&#91;1h])\n\n# Restart counts\nincrease(kube_pod_container_status_restarts_total&#91;1h])<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Put Guardrails in Place<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Right-sizing once does not stop the problem returning. Add guardrails so that new workloads start sensibly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">LimitRange for defaults and maximums<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: LimitRange\nmetadata:\n  name: container-defaults\n  namespace: team-a\nspec:\n  limits:\n  - type: Container\n    defaultRequest:\n      cpu: 100m\n      memory: 128Mi\n    default:\n      memory: 256Mi\n    max:\n      cpu: \"4\"\n      memory: 8Gi\n    maxLimitRequestRatio:\n      memory: \"1\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This gives every container a modest default and blocks absurd values. A <code>maxLimitRequestRatio<\/code> helps stop huge gaps between request and limit.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ResourceQuota per team<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: ResourceQuota\nmetadata:\n  name: team-a-quota\n  namespace: team-a\nspec:\n  hard:\n    requests.cpu: \"40\"\n    requests.memory: 160Gi<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Quotas turn requests into a budget. Teams that must stay inside a quota have an incentive to size honestly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Policy as code<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use Kyverno or OPA Gatekeeper to enforce rules such as &#8220;memory request must equal memory limit&#8221; or &#8220;CPU request may not exceed 4 cores without an approved label.&#8221;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: kyverno.io\/v1\nkind: ClusterPolicy\nmetadata:\n  name: require-resource-requests\nspec:\n  validationFailureAction: Enforce\n  rules:\n  - name: check-requests\n    match:\n      any:\n      - resources:\n          kinds: &#91;\"Pod\"]\n    validate:\n      message: \"CPU and memory requests are required.\"\n      pattern:\n        spec:\n          containers:\n          - resources:\n              requests:\n                cpu: \"?*\"\n                memory: \"?*\"<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Build it into CI\/CD<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Add a linter (for example kube-linter, Polaris or Kubescape) that flags missing or extreme resource settings in pull requests.<\/li>\n\n\n\n<li>Show an estimated cost impact of infrastructure changes in the PR.<\/li>\n\n\n\n<li>Include request efficiency in service dashboards so teams see it next to latency and error rate.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Let Autoscaling Do the Rest<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once requests reflect reality, autoscaling works much better.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>HPA:<\/strong> scale replicas on CPU, memory or custom metrics instead of keeping peak replica counts all day.<\/li>\n\n\n\n<li><strong>KEDA:<\/strong> scale on queues, events or schedules, including down to zero for idle services.<\/li>\n\n\n\n<li><strong>Node autoscaling:<\/strong> with honest requests, Cluster Autoscaler or Karpenter can pack workloads tightly and remove empty nodes. See [Karpenter vs Cluster Autoscaler: Cost Efficiency Comparison].<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Special Cases<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>JVM and other runtime-managed memory.<\/strong> Java services often need memory sized to heap plus metaspace and native overhead. Setting a request below real peak causes OOM kills. Use container-aware JVM flags and measure total working set, not just heap.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Startup spikes.<\/strong> Some applications use much more CPU during startup than at steady state. Use startup probes and consider a higher temporary allowance, or in-place resize where supported, rather than sizing permanently for the spike.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sidecars and DaemonSets.<\/strong> Service mesh proxies, log shippers and agents each have their own requests. Reviewing those can be one of the fastest wins because they multiply per pod or per node.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Batch and CI jobs.<\/strong> Their usage is bursty and short. Right-size by job type and use Spot nodes where interruptions are acceptable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Dev and staging.<\/strong> These environments are a common source of waste, because production-sized requests are copied into them. Use smaller defaults and fewer replicas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Mistakes<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Sizing from average usage only.<\/strong> Averages hide peaks. Use percentiles and maximums.<\/li>\n\n\n\n<li><strong>Using too short a window.<\/strong> One quiet day is not representative.<\/li>\n\n\n\n<li><strong>Cutting memory too aggressively.<\/strong> OOM kills cost far more than the saved memory.<\/li>\n\n\n\n<li><strong>Applying VPA automatically to everything.<\/strong> Roll out gradually and exclude critical singletons at first.<\/li>\n\n\n\n<li><strong>Declaring CPU limits mandatory or forbidden as dogma.<\/strong> Decide per workload class and measure throttling.<\/li>\n\n\n\n<li><strong>Forgetting init containers and sidecars<\/strong> when calculating a pod&#8217;s effective request.<\/li>\n\n\n\n<li><strong>Treating optimization as a project.<\/strong> It needs a recurring review.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">A Simple Monthly Routine<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Pull the top 20 workloads by (requested minus used) cost.<\/li>\n\n\n\n<li>Check throttling and OOM history for each.<\/li>\n\n\n\n<li>Apply the recommended change in staging, then production.<\/li>\n\n\n\n<li>Verify latency, restarts and error rate for a week.<\/li>\n\n\n\n<li>Log the saving and share it with the team.<\/li>\n\n\n\n<li>Review quotas and LimitRanges for any namespace that regressed.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What is a good CPU request efficiency target?<\/strong> Many teams aim for roughly 50 to 70 percent average utilization of requests for steady workloads, leaving headroom for spikes. Exact targets depend on how bursty and critical the workload is.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Do CPU requests or limits affect cost more?<\/strong> Requests. They determine how much node capacity is reserved. Limits mostly affect performance behavior, though they influence how teams set requests.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Will removing CPU limits cause noisy neighbours?<\/strong> CPU requests still guarantee each container a proportional share under contention, so neighbours cannot starve one another. The risk is greater for memory, which is why memory limits stay.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Is it safe to use VPA in Auto mode in production?<\/strong> It can be, for stateless workloads with multiple replicas and PodDisruptionBudgets, but pods may be restarted to apply new values unless in-place resize is available. Start with recommendation mode.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>How often should I re-size?<\/strong> Review monthly for the biggest workloads and after any major release or traffic change.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Over-provisioned requests quietly inflate node counts, and badly tuned CPU limits throttle applications and drive teams to inflate requests even further. Break the cycle by measuring requested versus actual usage, sizing from percentiles with sensible headroom, being deliberate about CPU limits, and adding guardrails with LimitRanges, quotas and policy. Do it gradually, watch reliability signals, and repeat it monthly.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>By Ra\u00fal P\u00e9rez \u00b7 Last updated: October 2026 \u00b7 Reading time: 14 min Here is a pattern that plays out [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":123,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[7],"tags":[],"class_list":["post-68","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kubernetes-finops"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Over-Provisioned Pods and CPU Limits: How to Stop Cloud Waste<\/title>\n<meta name=\"description\" content=\"Learn how oversized resource requests and misconfigured CPU limits waste cloud money and hurt performance. Includes PromQL queries\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/smartcloudspend.com\/?p=68\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Over-Provisioned Pods and CPU Limits: How to Stop Cloud Waste\" \/>\n<meta property=\"og:description\" content=\"Learn how oversized resource requests and misconfigured CPU limits waste cloud money and hurt performance. Includes PromQL queries\" \/>\n<meta property=\"og:url\" content=\"https:\/\/smartcloudspend.com\/?p=68\" \/>\n<meta property=\"og:site_name\" content=\"SmartCloudSpend\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-14T07:27:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-30T11:59:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/Optimizacion-Kubernetes-en-la-nube.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1774\" \/>\n\t<meta property=\"og:image:height\" content=\"887\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Raul\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Raul\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68\"},\"author\":{\"name\":\"Raul\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#\\\/schema\\\/person\\\/44ee75fea87758b75c9fa20bcb4736b5\"},\"headline\":\"Preventing Cloud Waste Caused by Over-Provisioned Pods and CPU Limits\",\"datePublished\":\"2026-10-14T07:27:06+00:00\",\"dateModified\":\"2026-10-30T11:59:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68\"},\"wordCount\":2175,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/smartcloudspend.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Optimizacion-Kubernetes-en-la-nube.png\",\"articleSection\":[\"Kubernetes FinOps\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68\",\"url\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68\",\"name\":\"Over-Provisioned Pods and CPU Limits: How to Stop Cloud Waste\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/smartcloudspend.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Optimizacion-Kubernetes-en-la-nube.png\",\"datePublished\":\"2026-10-14T07:27:06+00:00\",\"dateModified\":\"2026-10-30T11:59:23+00:00\",\"description\":\"Learn how oversized resource requests and misconfigured CPU limits waste cloud money and hurt performance. Includes PromQL queries\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/smartcloudspend.com\\\/?p=68\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#primaryimage\",\"url\":\"https:\\\/\\\/smartcloudspend.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Optimizacion-Kubernetes-en-la-nube.png\",\"contentUrl\":\"https:\\\/\\\/smartcloudspend.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/Optimizacion-Kubernetes-en-la-nube.png\",\"width\":1774,\"height\":887},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/?p=68#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/smartcloudspend.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Preventing Cloud Waste Caused by Over-Provisioned Pods and CPU Limits\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#website\",\"url\":\"https:\\\/\\\/smartcloudspend.com\\\/\",\"name\":\"SmartCloudSpend\",\"description\":\"Cloud services budget optimizer\",\"publisher\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/smartcloudspend.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#organization\",\"name\":\"SmartCloudSpend\",\"url\":\"https:\\\/\\\/smartcloudspend.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/smartcloudspend.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/cropped-Gemini_Generated_Image_8kqpol8kqpol8kqp-removebg-preview.png\",\"contentUrl\":\"https:\\\/\\\/smartcloudspend.com\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/cropped-Gemini_Generated_Image_8kqpol8kqpol8kqp-removebg-preview.png\",\"width\":453,\"height\":401,\"caption\":\"SmartCloudSpend\"},\"image\":{\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/smartcloudspend.com\\\/#\\\/schema\\\/person\\\/44ee75fea87758b75c9fa20bcb4736b5\",\"name\":\"Raul\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7528fdea3565b1d864e359aadcb71d1a08ebb6360994d6a7f695c45b0f3984ed?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7528fdea3565b1d864e359aadcb71d1a08ebb6360994d6a7f695c45b0f3984ed?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/7528fdea3565b1d864e359aadcb71d1a08ebb6360994d6a7f695c45b0f3984ed?s=96&d=mm&r=g\",\"caption\":\"Raul\"},\"sameAs\":[\"https:\\\/\\\/smartcloudspend.com\"],\"url\":\"https:\\\/\\\/smartcloudspend.com\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Over-Provisioned Pods and CPU Limits: How to Stop Cloud Waste","description":"Learn how oversized resource requests and misconfigured CPU limits waste cloud money and hurt performance. Includes PromQL queries","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/smartcloudspend.com\/?p=68","og_locale":"en_US","og_type":"article","og_title":"Over-Provisioned Pods and CPU Limits: How to Stop Cloud Waste","og_description":"Learn how oversized resource requests and misconfigured CPU limits waste cloud money and hurt performance. Includes PromQL queries","og_url":"https:\/\/smartcloudspend.com\/?p=68","og_site_name":"SmartCloudSpend","article_published_time":"2026-10-14T07:27:06+00:00","article_modified_time":"2026-10-30T11:59:23+00:00","og_image":[{"width":1774,"height":887,"url":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/Optimizacion-Kubernetes-en-la-nube.png","type":"image\/png"}],"author":"Raul","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Raul","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/smartcloudspend.com\/?p=68#article","isPartOf":{"@id":"https:\/\/smartcloudspend.com\/?p=68"},"author":{"name":"Raul","@id":"https:\/\/smartcloudspend.com\/#\/schema\/person\/44ee75fea87758b75c9fa20bcb4736b5"},"headline":"Preventing Cloud Waste Caused by Over-Provisioned Pods and CPU Limits","datePublished":"2026-10-14T07:27:06+00:00","dateModified":"2026-10-30T11:59:23+00:00","mainEntityOfPage":{"@id":"https:\/\/smartcloudspend.com\/?p=68"},"wordCount":2175,"commentCount":0,"publisher":{"@id":"https:\/\/smartcloudspend.com\/#organization"},"image":{"@id":"https:\/\/smartcloudspend.com\/?p=68#primaryimage"},"thumbnailUrl":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/Optimizacion-Kubernetes-en-la-nube.png","articleSection":["Kubernetes FinOps"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/smartcloudspend.com\/?p=68#respond"]}]},{"@type":"WebPage","@id":"https:\/\/smartcloudspend.com\/?p=68","url":"https:\/\/smartcloudspend.com\/?p=68","name":"Over-Provisioned Pods and CPU Limits: How to Stop Cloud Waste","isPartOf":{"@id":"https:\/\/smartcloudspend.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/smartcloudspend.com\/?p=68#primaryimage"},"image":{"@id":"https:\/\/smartcloudspend.com\/?p=68#primaryimage"},"thumbnailUrl":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/Optimizacion-Kubernetes-en-la-nube.png","datePublished":"2026-10-14T07:27:06+00:00","dateModified":"2026-10-30T11:59:23+00:00","description":"Learn how oversized resource requests and misconfigured CPU limits waste cloud money and hurt performance. Includes PromQL queries","breadcrumb":{"@id":"https:\/\/smartcloudspend.com\/?p=68#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/smartcloudspend.com\/?p=68"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/smartcloudspend.com\/?p=68#primaryimage","url":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/Optimizacion-Kubernetes-en-la-nube.png","contentUrl":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/Optimizacion-Kubernetes-en-la-nube.png","width":1774,"height":887},{"@type":"BreadcrumbList","@id":"https:\/\/smartcloudspend.com\/?p=68#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/smartcloudspend.com\/"},{"@type":"ListItem","position":2,"name":"Preventing Cloud Waste Caused by Over-Provisioned Pods and CPU Limits"}]},{"@type":"WebSite","@id":"https:\/\/smartcloudspend.com\/#website","url":"https:\/\/smartcloudspend.com\/","name":"SmartCloudSpend","description":"Cloud services budget optimizer","publisher":{"@id":"https:\/\/smartcloudspend.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/smartcloudspend.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/smartcloudspend.com\/#organization","name":"SmartCloudSpend","url":"https:\/\/smartcloudspend.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/smartcloudspend.com\/#\/schema\/logo\/image\/","url":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/cropped-Gemini_Generated_Image_8kqpol8kqpol8kqp-removebg-preview.png","contentUrl":"https:\/\/smartcloudspend.com\/wp-content\/uploads\/2026\/10\/cropped-Gemini_Generated_Image_8kqpol8kqpol8kqp-removebg-preview.png","width":453,"height":401,"caption":"SmartCloudSpend"},"image":{"@id":"https:\/\/smartcloudspend.com\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/smartcloudspend.com\/#\/schema\/person\/44ee75fea87758b75c9fa20bcb4736b5","name":"Raul","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/7528fdea3565b1d864e359aadcb71d1a08ebb6360994d6a7f695c45b0f3984ed?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/7528fdea3565b1d864e359aadcb71d1a08ebb6360994d6a7f695c45b0f3984ed?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7528fdea3565b1d864e359aadcb71d1a08ebb6360994d6a7f695c45b0f3984ed?s=96&d=mm&r=g","caption":"Raul"},"sameAs":["https:\/\/smartcloudspend.com"],"url":"https:\/\/smartcloudspend.com\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/posts\/68","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=68"}],"version-history":[{"count":3,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/posts\/68\/revisions"}],"predecessor-version":[{"id":245,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/posts\/68\/revisions\/245"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=\/wp\/v2\/media\/123"}],"wp:attachment":[{"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=68"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=68"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/smartcloudspend.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=68"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}