A cgroup can remain alive after its memory usage crosses memory.high. The boundary does not behave like a hard allocation ceiling: tasks in the cgroup are throttled and pushed into heavy reclaim pressure, and usage can remain above the configured value under extreme conditions.
That behavior makes memory.high materially different from memory.max. The former converts excess usage into execution cost and reclaim work. The latter is a hard limit that can lead to a cgroup OOM when reclaim cannot reduce usage enough.
The high boundary changes allocation behavior
The cgroup v2 memory controller accounts major user-space and kernel memory classes to a hierarchy. memory.current reports the current charge for a cgroup and its descendants, while memory.high defines a throttle boundary for that charged usage.
Once usage exceeds the high boundary, subsequent memory charging paths can force affected tasks through direct reclaim and throttling. The workload spends CPU time scanning reclaim candidates, may wait for writeback or swap activity, and can lose application throughput even though allocations have not reached a hard failure boundary.
This is a pressure mechanism rather than a reservation. A value of 4 GiB does not mean that the kernel always keeps the cgroup at or below exactly 4 GiB. Accounting races, reclaim progress, active working sets, and other memory-management conditions can leave usage above the boundary for some interval.
The default value is max, which disables this throttle boundary.
Direct reclaim moves cost into the workload
A high-boundary breach matters because reclaim is not free background cleanup. Tasks associated with new charges can be routed into direct memory reclaim. Their execution time is then partly consumed by attempts to free memory charged to the cgroup.
For file-backed pages, reclaim can discard clean cache pages or require dirty data to reach backing storage before those pages become reusable. Anonymous pages may require swap space when swapping is available and permitted. A workload with a large active set can therefore spend substantial time scanning pages that are quickly referenced again.
This creates a characteristic failure mode: memory usage looks bounded near the configured high value, yet latency rises and throughput falls. The limit is doing work precisely because the workload continues to demand memory beyond the boundary.
memory.events exposes a high counter for these incidents. The counter increases when cgroup processes are throttled and routed into direct reclaim after crossing the high boundary. It records boundary pressure events, not elapsed stall duration.
memory.high and memory.max enforce different boundaries
memory.max is the memory controller’s hard usage limit. When usage reaches that boundary and reclaim cannot reduce it, allocation pressure can put the cgroup into an OOM state and invoke the cgroup OOM killer.
memory.high does not invoke the OOM killer merely because the boundary is exceeded. Its enforcement path is deliberately recoverable: reclaim and throttling can slow the workload while an external controller observes pressure, adjusts resources, or terminates the workload through policy outside the memory controller.
This separation supports configurations in which a service has an operating boundary below an absolute safety boundary. For example, a cgroup can have a finite memory.high that applies sustained backpressure and a larger memory.max that prevents unbounded growth. Crossing the first boundary degrades execution; reaching the second can become a survival event.
The gap between the two values is therefore operationally significant. A narrow gap gives reclaim little room before the hard limit becomes relevant. A wider gap permits more transient overage but also allows a larger charged footprint.
Reclaimability controls the severity of throttling
Equal overages do not imply equal performance effects. The kernel must locate memory that can actually be reclaimed at acceptable cost.
A cache-heavy workload with cold clean pages may shed memory rapidly. A workload dominated by frequently touched anonymous pages can be much harder to reduce, especially when swap is unavailable or constrained. Dirty file cache can couple memory pressure to storage latency because reclaim may depend on writeback progress.
The active working set also matters. Reclaiming a page that is immediately faulted or read back does not produce durable relief. Repeated eviction and refault can convert a nominal memory cap into sustained CPU, storage, and latency pressure.
For this reason, memory.current near memory.high is insufficient as a performance signal. The event counters, memory composition in memory.stat, and memory pressure stall information provide separate evidence about enforcement frequency, charged memory classes, and time lost to pressure.
Hierarchy changes the source of pressure
cgroup v2 resource control is hierarchical. A task can reside in a leaf cgroup whose local configuration appears permissive while an ancestor imposes a tighter effective resource boundary across a larger subtree.
Memory accounting and events therefore need hierarchy-aware interpretation. memory.events is hierarchical and can reflect events generated below the cgroup being inspected. memory.events.local restricts counters to the local cgroup.
This distinction matters in service trees where a parent groups several workers. Pressure visible at the parent may come from one descendant, several descendants competing under the shared parent boundary, or a policy applied at the parent itself. Local counters help separate a leaf’s own events from aggregated subtree activity.
A similar issue appears when comparing charged usage after processes move between cgroups. Memory is generally charged to the cgroup that instantiated it and does not automatically migrate with a process. Process placement and memory ownership can therefore diverge for existing allocations.
Lowering the boundary can trigger synchronous work
Writing a lower value to memory.high can make the target cgroup immediately over-limit. With a normal blocking file descriptor, changing the value can involve synchronous reclaim, causing the administrative writer to spend CPU time on memory recovery.
The interface has a specific nonblocking behavior. When memory.high is opened with O_NONBLOCK, synchronous reclaim by the writer is bypassed. The target workload instead encounters reclaim or throttling on a later charge request.
That changes where the enforcement cost is paid, not the meaning of the boundary. It can protect a resource-management agent from doing substantial reclaim work itself, but it also means usage may remain above the new value until target tasks make suitable charge requests and reclaim progresses.
A workload that rarely allocates after the change can therefore take an extended period to fall below the new boundary.
Pressure can propagate beyond memory latency
Direct reclaim consumes CPU cycles, and reclaiming dirty or swapped pages can generate storage traffic. A memory control decision can consequently appear as CPU contention, I/O pressure, or application tail latency rather than as a simple allocation failure.
This coupling is important when memory.high is used as a steady-state control. Frequent high events indicate repeated contact with the throttle boundary. Rising memory PSI indicates that tasks are losing execution time to memory pressure. Storage pressure can increase when reclaim repeatedly requires writeback or swap I/O.
The boundary is most accurately treated as a feedback mechanism. It transforms excess charged memory into reclaim effort and throttling, preserving a distinct hard-failure boundary at memory.max. That separation gives cgroup v2 a way to express memory pressure before memory exhaustion becomes an OOM event.