Linux overcommit policy controls admission of certain virtual-memory commitments. It is separate from allocating resident physical pages, choosing an OOM victim, and enforcing a container’s memory limit. A successful allocation can precede physical demand, but that does not make all allocations free or guarantee that later accesses will succeed under every resource constraint.

Virtual commitment differs from residence

An allocator such as malloc may obtain memory through brk or mmap and may reuse an existing arena without making a new system call. Anonymous pages are commonly populated lazily. Address-space metadata, page tables, and actual page faults still consume resources; the cost depends on what the application requests and touches.

Committed_AS is an accounting quantity, not the process resident-set sum and not a measurement of current pressure. Mapping type matters: private writable mappings can require commitment even before every page becomes resident, while ordinary shared or read-only file-backed mappings have different accounting. A large virtual-size figure cannot by itself identify the application responsible for a physical-memory shortage.

Three admission policies

Mode 0 is the default heuristic policy. It rejects obvious overcommits while allowing allocations that would exceed a simple resident-memory budget. Its decision is not a promise that every accepted byte has dedicated RAM. Mode 1 skips the overcommit admission check, which can support sparse workloads, but address-space limits, mapping limits, and other allocation failures still apply.

Mode 2 enforces stricter commitment accounting. The nominal CommitLimit is derived from swap plus a configured amount of RAM: ratio-based calculation excludes hugetlb-reserved memory, while a nonzero overcommit_kbytes supplies an absolute allowance instead of the ratio. Kernel reserves and the calling context can further affect admission. The displayed difference from Committed_AS is therefore useful context rather than a universal maximum guaranteed allocation.

A chargeable allocation may fail with ENOMEM when it cannot fit that budget. This can expose capacity problems earlier, including commitments needed by fork and later permission changes. Fork accounting follows applicable mappings and copy-on-write obligations; it is not simply twice the parent’s resident set. Some applications deliberately reserve sparse address space, so changing policy can change their startup behavior.

Strict accounting is not OOM immunity

Mode 2 reduces one class of overcommit risk, but does not override cgroup memory limits, NUMA constraints, other kernel allocations, or all later memory demands. A task can still encounter allocation failure or an OOM event. Do not promise that choosing mode 2 protects a particular worker from being killed.

OOM victim selection is a separate policy using the relevant scope and eligibility rules, not random punishment and not a decision made by the CPU scheduler. The killed process need not be the task that most recently requested memory. Inspect the event’s host or cgroup context before attributing responsibility from the victim’s name alone.

Containers share the host kernel and should not be assumed to own an independent vm.overcommit_memory policy. Their memory controls add another boundary. Virtual machines have their own guest kernel accounting, while host backing and ballooning introduce additional constraints. Record which layer each metric belongs to before comparing budgets.

When it breaks

A workload can successfully reserve memory and then encounter reclaim, swap activity, or OOM when demand grows. Neither mode 0 nor mode 1 guarantees that the failure will be slow, that swap is available, or that a particular process dies. Compare demand and latency with actual reclaim and memory-pressure evidence.

Conversely, mode 2 can reject a request despite apparently free RAM because the commitment budget is already occupied. That is one possible cause of ENOMEM, not a diagnosis from the error alone. Process resource limits, excessive mapping counts, and application configuration deserve separate checks.

Large nominal headroom does not prove the ratio is too conservative, and small headroom does not automatically justify increasing it. Budget changes can admit demand that later competes for real resources. Plan from workload requirements and recovery margin, preserve configuration context, and test changes outside production before rollout.

Committed_AS and three admission policies precede later physical demand. Nominal commit headroom differs from available RAM; cgroup and NUMA constraints remain even in mode 2. No article example was run for this graphic.
Overcommit controls commitment admission; accepted requests still face later physical and cgroup constraints.

Check it quickly

Save this as overcommit_probe.py and run python3 overcommit_probe.py. It reads only the named proc files, prints the observed mode and accounting fields, and performs synthetic parser checks. It does not reserve memory, trigger OOM, or suggest automatic tuning.

from pathlib import Path
import re


def read_value(path):
    try:
        return Path(path).read_text(encoding="utf-8").strip()
    except OSError as error:
        print("SKIP", path, type(error).__name__)
        return None


def meminfo_kb(text):
    return {name: int(value) for name, value in re.findall(
        r"^(MemTotal|SwapTotal|CommitLimit|Committed_AS):\s+(\d+)\s+kB\s*$",
        text, re.M)}


def report(mode, info):
    names = {"0": "heuristic", "1": "always overcommit", "2": "strict accounting"}
    lines = ["mode: " + names.get(mode, "unknown or unreadable")]
    limit, committed = info.get("CommitLimit"), info.get("Committed_AS")
    if limit is not None and committed is not None:
        lines.append("nominal commit headroom: %s kB" % (limit - committed))
    else:
        lines.append("commit headroom unavailable")
    if mode == "2":
        lines.append("Commit accounting can reject chargeable requests; other limits still apply")
    else:
        lines.append("CommitLimit is not the enforced mode-2 ceiling in this mode")
    lines.append("This snapshot is not available RAM, a cgroup budget, or OOM immunity")
    return lines


fixture = meminfo_kb("CommitLimit: 100 kB\nCommitted_AS: 0 kB\n")
assert "nominal commit headroom: 100 kB" in report("2", fixture)
assert meminfo_kb("CommitLimit: bad kB\nCommitted_AS: 7 MB\n") == {}
assert "commit headroom unavailable" in report("2", {})
assert report("9", {})[0] == "mode: unknown or unreadable"
for mode in ("0", "1", "2"):
    assert "OOM immunity" in report(mode, fixture)[-1]

mode = read_value("/proc/sys/vm/overcommit_memory")
ratio = read_value("/proc/sys/vm/overcommit_ratio")
kbytes = read_value("/proc/sys/vm/overcommit_kbytes")
text = read_value("/proc/meminfo")
if mode is None or text is None:
    print("SKIP live overcommit report; synthetic checks passed")
else:
    info = meminfo_kb(text)
    print("overcommit_memory=%s overcommit_ratio=%s overcommit_kbytes=%s" % (mode, ratio, kbytes))
    print("Observed kB fields:", info)
    for line in report(mode, info):
        print(line)

Expect a live snapshot or an explicit SKIP message. Zero committed memory remains a valid value. The revised example passed with Python 3.12.14 on Linux; synthetic checks cover malformed input, absent fields, and all three modes. Reading these counters does not test real allocation rejection or recovery.

Further reading

Sources