What are Kubernetes resource requests and limits?

A resource request is the amount of CPU and memory Kubernetes reserves for a container when it places the Pod on a node. A resource limit is the maximum the container may use: the kernel throttles CPU above the limit and kills the container with an out-of-memory (OOM) error when memory goes above it. The scheduler places Pods by their requests, not their actual usage, so requests decide how many nodes a cluster needs and what it costs.

Requests vs limits

Both are set per container under resources:

yaml
resources:
  requests:
    cpu: 250m
    memory: 256Mi
  limits:
    memory: 256Mi
Request Limit
Used by The scheduler, to pick a node with enough unreserved capacity The kernel on the node, at run time
CPU Reserved share. Under contention, CPU time is split in proportion to requests Hard cap. Above it, the container is throttled
Memory Reserved amount Ceiling. Above it, the container can be OOM-killed
If unset Copied from the limit when a limit is set, otherwise zero No cap: the container can use whatever is free on the node

A container can use more than its request when the node has spare capacity. The Kubernetes documentation describes memory limits as enforced reactively: the kernel kills a container over its limit when it detects memory pressure, not the moment usage crosses the line. CPU is compressible, so going over a CPU limit slows the container down but never kills it.

CPU and memory units

One CPU unit is one physical core or one virtual core (vCPU), depending on the node. 100m means 100 millicores, a tenth of a core, and 1000m equals 1. Kubernetes accepts no precision finer than 1m.

Memory is in bytes with decimal or binary suffixes. M is a megabyte (1,000,000 bytes) and Mi is a mebibyte (1,048,576 bytes), so 256Mi is about 268 MB. The case matters: 400m of memory is 0.4 bytes, a common typo for 400Mi.

Why requests set the bill

The scheduler adds up the requests of every Pod on a node and only places a new Pod if its requests fit in the remaining allocatable capacity. It does not look at real usage. A Pod that requests 2 vCPU and uses 0.1 vCPU still blocks 2 vCPU, and the cluster autoscaler adds nodes when pending Pods’ requests do not fit.

That makes requests the main lever for cost. Oversized requests leave nodes full on paper and idle in practice; rightsizing is the practice of setting them from measured usage. Limits do not reserve capacity, so they do not change the bill.

Quality of service classes and eviction

Kubernetes assigns every Pod a quality of service (QoS) class from its requests and limits. When a node runs short of memory or disk, the kubelet evicts Pods in this order.

QoS class Criteria Eviction order
BestEffort No container sets any CPU or memory request or limit First
Burstable At least one request or limit set, but not Guaranteed Second
Guaranteed Every container sets CPU and memory limits equal to its requests Last

Under resource pressure, only Pods using more than their requests are candidates for eviction. A container whose memory limit equals its memory request is stopped by its own limit before it can grow far past the request, so many teams set the two to the same value.

OOM kills vs CPU throttling

A container killed for exceeding its memory limit shows OOMKilled as the termination reason and restarts according to the Pod’s restart policy. A container that hits its CPU limit keeps running but receives less CPU time in each scheduling period, which shows up as higher latency. Throttling can happen even when average CPU usage looks low, which is why many teams skip CPU limits for latency-sensitive services. The trade-offs are in should you set CPU limits in Kubernetes.

Namespace defaults with LimitRange and ResourceQuota

A LimitRange sets default requests and limits for containers in a namespace that do not declare them, plus minimum and maximum values per container. A ResourceQuota caps the total requests and limits across a namespace. When a quota covers CPU or memory, Pods that do not specify those values can be rejected, so quotas are usually paired with a LimitRange that fills in defaults.

Requests and autoscaling

The Horizontal Pod Autoscaler measures CPU and memory utilization as a percentage of the request. A target of 70% on a container that requests 500m scales out at 350m of use. If a container has no request for the metric, the autoscaler takes no action on it. Changing requests therefore changes when the autoscaler adds replicas. How Kubernetes autoscaling works covers the autoscalers in more detail.

Changing requests without restarting Pods

Before in-place resize, changing a request meant replacing the Pod. In-place Pod resize, first available in Kubernetes 1.27, is stable since Kubernetes v1.35. It lets you change CPU and memory requests and limits on a running Pod. Each container’s resizePolicy decides whether a change applies live (NotRequired, the default) or restarts the container (RestartContainer). A resize cannot change the Pod’s QoS class, and the kubelet only makes a best-effort attempt to avoid OOM kills when lowering memory limits.

How Cloudfleet uses requests

In Cloudfleet Kubernetes Engine (CFKE), node auto-provisioning reads Pod resource requests, labels and affinity rules to choose the number and size of nodes, so accurate requests translate directly into smaller nodes and a lower bill.

On this page