Interactive tool
Requests and limits, from measurements
Most OOMKilled incidents come from a limit set by guess rather than measurement. This turns what you observed into numbers you can paste, and explains each one — including why it does not suggest a CPU limit.
Runs in your browser · nothing is sent anywhere
Measured input
Steady-state usage under normal traffic
Highest you have observed, including startup
Steady-state usage
Highest you have observed
kubectl top pod <pod> --containers
Sample several times across a full load cycle. One reading cannot show a peak, and a guessed input produces a guessed limit — which is how OOMKilled happens in the first place.
Suggested
resources:
requests:
memory: "256Mi"
cpu: "150m"
limits:
memory: "512Mi"
# No CPU limit set — see the note above.Why these numbers
- Memory request is set near typical usage (180 MiB). Requests are what the scheduler reserves, so inflating them makes the cluster look full while nodes sit idle.
- Memory limit is at least 25% above your observed peak (320 MiB), rounded up to a common size. The limit is the kill line — crossing it means SIGKILL from the kernel with no graceful shutdown.
- No CPU limit is suggested. CPU is compressible: a container may use more than its request whenever the node has spare CPU, and going over a limit throttles it rather than killing it — tight CPU limits are a common cause of latency nobody can explain. Memory offers no such forgiveness, which is why it gets a limit and CPU does not.
Related troubleshooting
What requests and limits are
When you run a container on Kubernetes you can tell it two things about resources. A request is what the container needs, and a limit is the most it may use.
They do different jobs. The request is used to decide which machine the container goes on — the scheduler subtracts it from that node's free capacity and reserves it. The limit is enforced while the container runs.
Using it
Enter what you have observed the container actually using, and the calculator suggests a request and a limit with the reasoning shown rather than as bare numbers.
Observed usage is the input that matters, so take it from real traffic rather than a guess: kubectl top pod for a snapshot, or your metrics for a percentile over a week — a peak that happens once a day is the number that decides whether the pod survives.
What this checks
- Suggested CPU and memory requests and limits from usage figures you provide.
What it cannot know
- Observe your workload's real usage, its peaks or its startup spike.
- Know your node sizes, or whether your cluster uses CPU limits at all.
Check it for real
kubectl top pod <pod> --containers
Recent CPU and memory per container. It needs the Metrics Server installed in the cluster, and it is a snapshot, so watch it under real load. kubectl top
Where the two behave differently
Memory and CPU are not symmetric, and this is the thing worth knowing. Memory is incompressible: a container over its memory limit is killed, exits 137 with OOMKilled: true, and under a restart policy this looks like a crash loop. CPU is compressible: over its CPU limit a container is throttled, which shows up as latency at the tail rather than as an obvious failure.
Which is why whether to set CPU limits is genuinely contested. Some teams set CPU requests only, and both for memory, on the grounds that throttling a service to protect a node it was not threatening costs more than it saves. The argument the other way is that without limits one container can starve its neighbours, and predictable throttling beats unpredictable contention. Which applies depends on whether your nodes are shared and how tight your latency targets are.
Requests set well above real usage have a quieter cost: they are reserved whether or not they are used, so the cluster runs out of schedulable capacity while the nodes look idle. The symptom is a pod stuck Pending with no error, because nothing has failed — the scheduler is still waiting for somewhere to put it.
Terms used here (1)plain definitions
Short definitions for the vocabulary on this page, in case any of it is new. Each links to the full entry.
- Auto Scaling
- The ability to automatically adjust the number of running compute resources based on real-time demand. Auto scaling ensures applications can handle traffic spikes without over-provisioning during quiet periods, optimizing both performance and cost.
Questions people ask about this
What is the difference between requests and limits?
A request is what the scheduler reserves for the container, and it is what decides which node the pod lands on. A limit is the ceiling enforced while it runs.
They are different jobs, which is why they are different numbers. Requests are about placement; limits are about containment.
What happens if a container exceeds its memory limit?
The kernel terminates it — memory cannot be throttled, only reclaimed. The container exits 137 with Reason: OOMKilled, and under a restart policy this presents as a restart loop: it starts, memory climbs, it is killed, it starts again. The exit code explainer covers reading that signature.
Should I set CPU limits?
This one is genuinely contested, so treat any confident answer with suspicion — including this one.
CPU is compressible: a container over its CPU limit is throttled rather than killed, and throttling shows up as latency at the tail rather than as an obvious failure. That is why a number of teams set CPU requests without limits, and set both for memory, on the grounds that throttling a service to protect a node it was not threatening costs more than it saves.
The argument the other way is that without limits one container can starve its neighbours, and that predictable throttling is easier to reason about than unpredictable contention. Which applies depends on whether your nodes are shared and how tight your latency targets are.
Why is my pod stuck in Pending?
Usually because no node has the requested amount free. A request is a reservation, subtracted from a node's advertised capacity whether or not the container uses it — so requests set well above real usage quietly shrink the cluster, and nothing errors. Nothing has failed; the scheduler is still waiting for somewhere to put it.
Did this get you to an answer?
No text box on purpose — please do not paste production logs anywhere
Something wrong or out of date? Report it
Tools that go with this
- Kubernetes Manifest AnalyzerPaste a manifest. Removed API versions and newer changes (gitRepo, externalIPs, Ingress NGINX), privileged containers, missing limits, absent probes, plaintext secrets — each linked to the failure it causes.
- Container Exit Code ExplainerWhat 137, 143 and 139 mean, and the rule behind them.
- Error Budget CalculatorWhat an availability target allows, and the burn rate.