Resource requests and limits are among the most misunderstood settings in Kubernetes, and misconfiguring them causes a remarkable range of problems: pods stuck pending, applications throttled for no obvious reason, mysterious restarts and clusters that cost far more than they should. Understanding what each setting actually does makes most of those problems easy to diagnose.
Two Different Jobs
A request is the amount of a resource a container is guaranteed and the amount the scheduler uses to decide where to place a pod. A limit is the maximum the container is allowed to use. The scheduler looks only at requests when placing pods. Limits are enforced on the node at runtime.
This distinction explains a lot. A node can look nearly idle in actual usage while being “full” from the scheduler’s point of view, because the sum of requests has reached the node’s allocatable capacity. New pods then sit in a pending state.
CPU and Memory Behave Differently
CPU is a compressible resource. If a container tries to use more CPU than its limit, it is throttled: slowed down, but not killed. This can show up as latency spikes in an application that otherwise looks healthy.
Memory is not compressible. If a container exceeds its memory limit, the kernel’s out-of-memory handling terminates it, and Kubernetes reports the container as killed for running out of memory, typically visible as an OOMKilled reason. The container is then restarted according to its restart policy.
Because of this, many teams set memory limits carefully, often equal to memory requests, while being more cautious about strict CPU limits. Opinions differ on CPU limits, so test the behavior for your own workloads and check current guidance for your Kubernetes version.
Quality of Service Classes
Kubernetes assigns each pod a quality of service (QoS) class based on its requests and limits, which influences which pods are evicted first when a node is under memory pressure:
| QoS Class | How It Is Assigned | Eviction Priority Under Pressure |
|---|---|---|
| Guaranteed | Every container has requests equal to limits for CPU and memory | Last to be evicted |
| Burstable | At least one request or limit set, but not Guaranteed | Middle |
| BestEffort | No requests or limits at all | First to be evicted |
Running important workloads as BestEffort is a common accident. Production pods should almost always have explicit requests.
How to Choose Starting Values
Guessing is the usual first step, but you can do better by observing:
- Run the workload under realistic load in a test environment.
- Observe typical and peak usage over a representative period using your metrics system.
- Set the request near typical sustained usage, so the pod gets what it normally needs.
- Set the memory limit with headroom above observed peaks to avoid needless kills.
- Revisit after releases that change behavior, since usage drifts over time.
Tools that recommend values based on observed usage exist, including vertical autoscaling components. They can be valuable, but treat their output as input to a decision, and check the documentation for how they interact with horizontal autoscaling.
Requests, Autoscaling and Cost
Requests drive more than scheduling. Horizontal pod autoscaling based on CPU utilization typically measures usage as a percentage of the request, so an inflated request makes utilization look low and scaling lag, while a tiny request makes the autoscaler overreact. Cluster autoscalers add nodes based on pending pods’ requests, so oversized requests translate directly into extra nodes and extra spending.
This is why right-sizing matters for cost: you pay for the nodes, and nodes are sized by the requests placed on them, not by what pods actually use.
Namespace Guardrails
Platform teams can prevent runaway or missing values using namespace-level controls. A LimitRange can set defaults and bounds for containers, and a ResourceQuota can cap the total resources a namespace may request. Together they stop a single team from accidentally consuming a shared cluster, and they guarantee every pod has at least baseline requests.
A Realistic Example
Suppose a team deploys an API service with a CPU request far larger than it ever uses, because someone copied values from a heavier service. Each pod reserves much more than it needs, so the scheduler fits only a few pods per node and the cluster keeps adding nodes. Meanwhile a background worker in the same namespace has a tight memory limit and gets killed during its busiest batch, restarting repeatedly. After reviewing real usage, the team lowers the API’s request to match observed demand, raises the worker’s memory limit to leave headroom above its peak, and adds a LimitRange so new services start with sensible defaults. Scheduling pressure eases and the restarts stop.
Troubleshooting Quick Reference
- Pods pending with insufficient resource messages: compare requests against node allocatable capacity, not actual usage.
- Containers restarting with OOMKilled: the memory limit is too low for peak usage, or the application leaks memory.
- High latency with low average CPU: check for CPU throttling against limits.
- Evictions during node pressure: look at QoS class and consider adding requests.
Frequently Asked Questions
Should requests and limits be equal? For memory, setting them equal is a common safe choice. For CPU, it depends on workload behavior, and some teams set requests without limits. Test and monitor.
What happens if I set no requests at all? The pod becomes BestEffort, may be scheduled onto crowded nodes and is the first candidate for eviction. Avoid this for anything that matters.
Why is my pod pending when the node looks idle? The scheduler counts requests, not usage. The sum of requests may already fill the node.
How often should I revisit values? After significant releases, traffic changes or when cost reviews flag waste. Many teams review quarterly.
Do init containers and sidecars count? Yes, they contribute to a pod’s effective resource needs, so account for them when sizing. Check the Kubernetes documentation for the exact calculation.
Next Step
Pick one namespace, list every pod without explicit requests, and compare configured values with observed usage over a typical week. Fix the five biggest mismatches, then add a LimitRange so the problem does not return.
By SkyStackHub Editorial · Updated November 4, 2026
- Kubernetes requests and limits
- pod scheduling
- resource management
- OOMKilled