PostgreSQL’s architecture makes it especially vulnerable to the Linux Out‑of‑Memory (OOM) killer. The postmaster forks a backend per client, all of which share critical buffers, WAL segments and lock tables. If the OOM killer terminates any backend that is touching shared memory, the kernel leaves those pages in an undefined state. The postmaster interprets this as possible corruption, aborts every transaction and shuts down all remaining backends, forcing a full crash‑recovery on restart. The result is a multi‑minute outage that can affect every consumer of the database [1].

Overcommit policies explained

Linux offers three vm.overcommit_memory modes:

  • 0 – Heuristic (default): the kernel prevents obviously impossible allocations but otherwise allows overcommit.
  • 1 – Always: every malloc succeeds; the OOM killer later intervenes if physical memory runs out.
  • 2 – Strict: the kernel tracks the total Committed_AS and refuses any allocation that would exceed a pre‑computed CommitLimit.

In strict mode the kernel instantly returns ENOMEM when a process asks for more memory than the limit permits. PostgreSQL treats this as a regular query error, rolls back the transaction and keeps the postmaster alive, preserving all other connections [1]. The trade‑off is that the database must be run on a machine with a predictable memory footprint, because any unrelated process that consumes the commit budget can cause benign‑looking ENOMEM errors.

The phantom‑memory bug

Ubicloud discovered a severe accounting leak in Linux 6.5 that inflated Committed_AS by hundreds of gigabytes on modest VMs. The leak stemmed from a one‑character regression in mm/mremap.c: the error check for do_vmi_munmap() was changed from < 0 to !, causing the kernel to add to Committed_AS on every successful mremap instead of only on failure. This produced “phantom” committed memory that silently grew with uptime, eventually crossing the strict overcommit limit and triggering spurious ENOMEM failures [2][3]. The bug was fixed in Linux 6.8 with a one‑line revert.

Deriving a safe CommitLimit

After the bug was patched, Ubicloud settled on a simple heuristic for the commit limit:

overcommit_kbytes = total_memory_kb × 0.8 + 2 GB
  • 80 % of RAM reserves space for kernel structures (page tables, slab caches, network buffers) that never appear in userspace accounting.
  • + 2 GB covers the virtual address space that side‑car processes (prometheus, wal‑g, Go exporters) reserve via mmap. In production data more than 96 % of servers see less than 1 GB of side‑car committed memory, so a flat 2 GB buffer protects the database from silently losing its commit budget [1].

The formula is applied via vm.overcommit_kbytes because it allows a fixed offset that a pure ratio cannot express. On a 4 GB VM the +2 GB is 50 % of RAM; on a 64 GB VM it is only 3 %, yet it still guarantees headroom for auxiliary services.

Business impact

  • Reduced downtime – Strict overcommit turns a single OOM kill that would crash the whole cluster into a per‑query error, keeping the service available.
  • Predictable capacity planning – The 80 % + 2 GB rule gives architects a clear ceiling for workload sizing, avoiding costly over‑provisioning.
  • Lower risk of data loss – By preventing uncontrolled shared‑memory corruption, the configuration eliminates the need for emergency manual recovery and the associated operational expense.