CPU Throttling High
!!! danger "Severity: warning" Target response: 30m. A container is being CPU-throttled by the Linux CFS scheduler for a significant fraction of its runtime — latency without the CPU-usage graph looking "hot."
What this alert means
CFS throttling = the kernel capping a container at its CPU limit. The
container can be throttled hard while sitting well under 100% average
usage, so HighCPUUsage won't catch it. Throttling shows up as latency,
timeouts, and slow health checks.
# Fraction of scheduler periods in which the container was throttled.
sum by (namespace, pod, container) (rate(container_cpu_cfs_throttled_periods_total[5m]))
/
sum by (namespace, pod, container) (rate(container_cpu_cfs_periods_total[5m]))
> 0.25
Sustained throttling >25% means the container spends a quarter of its
scheduling periods waiting for CPU it's not allowed to use — often the
hidden cause of a co-firing HighAPILatency.
Quick diagnostics
# WHERE: Grafana → Explore (Prometheus) or Prometheus /graph.
# WHAT: the throttled-periods ratio for the alerting container over time.
# READ: 0 = healthy. >0.1 = throttled 10%+ of periods (noticeable). >0.25
# = the alert threshold, real latency impact. Rising trend = getting worse.
rate(container_cpu_cfs_throttled_seconds_total{namespace="<namespace>",pod="<pod>",container="<container>"}[5m])
# WHERE: shell with kubectl context set.
# WHAT: the CPU request vs limit for the throttled container.
# READ: a low limit relative to request (or a limit barely above request)
# throttles under normal bursts. limit == request with bursty work is a
# classic throttling setup. No limit set = shouldn't throttle (recheck).
kubectl get pod -n <namespace> <pod> -o jsonpath='{range .spec.containers[*]}{.name}: req={.resources.requests.cpu} lim={.resources.limits.cpu}{"\n"}{end}'
# WHERE: Grafana → Explore or Prometheus /graph.
# WHAT: actual CPU usage vs the limit, to size a fix.
# READ: if usage rides just under the limit and throttling is high, the
# limit is too low — raise it. If usage is spiky, the limit is fine on
# average but too low for bursts — raise the limit, not the request.
sum by (pod) (rate(container_cpu_usage_seconds_total{namespace="<namespace>",pod="<pod>"}[5m]))
Severity & urgency
| Severity | Pager? | Target response | Business impact |
|---|---|---|---|
| Warning | No — chat only | 30m | Latency / timeouts under load |
Diagnostic steps
- Confirm throttling is current (ratio query above).
- Check limits — request vs limit for the container.
- Correlate — does it line up with a latency alert or a traffic peak?
- Right-size — raise the CPU limit (or remove it for latency-critical, well-behaved workloads) and redeploy.
Common causes & fixes
| Symptom | Diagnosis | Fix |
|---|---|---|
| Limit ≈ request, bursty app | High throttle ratio at peaks | Raise limit to cover bursts |
| Limit far below usage | Usage rides the ceiling | Raise limit to p95 usage + headroom |
| Throttling only at deploy | Startup CPU spike | Raise limit or add startup probe slack |
Escalation
- Primary —
@sre-oncallin#mm-incidents. - Service owner — to agree new limits if the workload is theirs.
Required Prometheus labels
Diagnostics use namespace, pod, container. Provided by cAdvisor
(container_cpu_cfs_*).
Related runbooks
- High API Latency — throttling is a frequent hidden cause.
- High CPU Usage — the sibling that fires on raw usage, not throttling.