# Memory Over-Provisioned

> No memory rightsizing recommendation is produced by this rule at all. The 1 signal it previously used, an HPA `ScalingLimited` condition, measures replica count, not per-container memory, and acting on it risks OOM kills. Abstaining was chosen over shipping an unsound recommendation.

Source: https://zop.dev/integrations/kubernetes/recommendations/memory-over-provisioned
Updated: 2026-08-19

---

## Stated plainly: this rule abstains

The rule is registered so the catalogue stays stable across releases, and it returns no
recommendation for any workload. That is the current, intended behaviour: not a bug, not a
coverage gap awaiting data, and not something a permission or metric on your side will change.

Publishing that is more useful than implying a capability that does not exist.

## The signal it used to run on, and why it was wrong

It keyed off an HPA reporting `ScalingLimited` with reason `TooFewReplicas`, the autoscaler
wanting to scale below `minReplicas`.

That is a statement about **replica count**. It says the workload as a whole has more copies than
demand justifies. It says nothing whatsoever about whether each pod's per-container memory
request exceeds that container's working set.

Both can be true at once in either direction. A workload can be replica-over-provisioned while
its memory requests are correctly sized, or even too small. Cutting memory requests on that
evidence is a coin flip dressed as a recommendation.

## Why the consequence is worse than for CPU

Memory is incompressible. There is no throttling equivalent.

Set a memory request below the actual working set and the kernel OOM-kills the container. On a
StatefulSet backing PersistentVolumes that means a data-path stall and eviction, on a pod whose
identity and storage are pinned to its ordinal. The cost of being wrong is not a slow service.
It is a restarted one, possibly mid-write.

Under evidence-sufficiency, an action whose failure mode is destructive requires an authoritative
observation. Nothing available today provides one.

## What would make it emit

A memory-utilization producer: working-set p95 over a real observation window, from VPA
recommendations or a metrics pipeline that retains a series. `metrics-server` cannot supply this, because
it exposes point-in-time snapshots, which is exactly why the HPA-condition workaround was
attempted in the first place.

Until such a producer is wired through, the rule stays silent. Re-keying it off
`hasConditionReason` for memory was considered and explicitly rejected.

## Checking your own memory headroom meanwhile

VPA in recommendation-only mode is the practical substitute, since it observes and suggests without
applying:

```bash
kubectl get vpa -A -o json | jq -r '
  .items[] | .metadata.namespace + "/" + .metadata.name + "\t" +
  ([.status.recommendation.containerRecommendations[]? |
    .containerName + ":" + .target.memory] | join(" "))'
```

Compare `target.memory` against the request in the pod spec, and treat anything within roughly
20% as correctly sized.
