PostgreSQL and the OOM Killer: Why We Use Strict Memory Overcommit
Ubicloud Postgres is now available on Google Cloud! Click here to sign up
Use CaseLog in<br>Sign up
Star us<br>Log in<br>Sign up
Loading...
All Blog Posts
All Blog Posts<br>PostgreSQL and the OOM Killer: Why We Use Strict Memory Overcommit
Ubicloud Price Adjustment<br>ClickHouse PostgreSQL powered by Ubicloud: Fast transactions and analytics
Virtualizing NVIDIA HGX B200 GPUs with Open Source
Keeping Documentation Up-To-Date via Automated Screenshot Generation
End-to-End OCR with Vision Language Models
Hardware Touch, Stronger SSH
AI Coding: A Sober Review
Does MHz still matter?
Life of an inference request (vLLM V1): How LLMs are served efficiently at scale
Ubicloud Premium Runners: 2x Faster Builds, 10x Larger Cache
PostgreSQL Performance: Local vs. Network-Attached Storage
Ubicloud PostgreSQL: New Features, Higher Performance
Building Burstables: cpu slicing with cgroups
Worry-free Kubernetes, with price-performance of bare metal
Ubicloud's Thin CLIent approach to command line interfaces
Dewey.py: Rebuilding Deep Research with Open Models
Ubicloud Burstable VMs starting at $0.01 per hour
Debugging Hetzner: Uncovering failures with powerstat, sensors, and dmidecode
Cloud virtualization: Red Hat, AWS Firecracker, and Ubicloud internals
OpenAI o1 vs. QwQ-32B: An Analysis
Making GitHub Actions and Docker Layer Caching 4x Faster
EuroGPT: Open source and privacy conscious alternative to ChatGPT Enterprise
Private Network Peering under 200 Lines<br>Lantern on Ubicloud: Build AI applications with PostgreSQL<br>Elastic-Quality Full Text Search on Postgres: Fully managed ParadeDB on Ubicloud<br>Ubicloud Load Balancer: Simple and Cost-Effective<br>13 Years of Building Infrastructure Control Planes in Ruby<br>Difference between running Postgres for yourself and for others<br>Ubicloud Block Storage: Encryption<br>Announcing New Ubicloud Compute Features<br>How we enabled ARM64 VMs<br>Ubicloud Firewalls: How Linux Nftables Enables Flexible Rules<br>Improving Network Performance with Linux Flowtables<br>EU's new cloud portability requirements - What do they mean?<br>Ubicloud hosted Arm runners, 100x better price/performance<br>Building block storage for the cloud with SPDK (non-replicated)<br>Open and portable Postgres-as-a-service<br>Learnings from Building a Simple Authorization System (ABAC)<br>vCPU, thread, core, node, socket. What do CPU terms mean these days?<br>Introducing Ubicloud
PostgreSQL and the OOM Killer: Why We Use Strict Memory Overcommit<br>April 27, 2026 · 10 min read<br>Burak Yucesoy<br>Principal Software Engineer
Our team members built and operated five managed PostgreSQL services over the past 15 years. Across all of them, one configuration has remained constant: strict memory overcommit.
In this blog post, we will explain how strict memory overcommit protects your database from catastrophic OOM (out of memory) kills. We will also share how a three-character kernel bug forced us to temporarily disable this setting. Finally, we will explain our heuristic for determining the right memory overcommit limit. Hopefully, this will help you find the right setting for your workloads.
Why PostgreSQL Can't Tolerate the OOM Killer<br>Strict Overcommit: Fail Early, Not Catastrophically<br>Discovery<br>Narrowing It Down<br>Fleet-Wide Analysis<br>The One-Character Bug<br>Setting the Commit Limit<br>Why 80%<br>Why +2 GB<br>Implementation<br>Conclusion
Why PostgreSQL Can't Tolerate the OOM Killer<br>Linux allows processes to allocate more virtual memory than what is physically available. When a process allocates memory, for example with malloc(), the kernel reserves virtual address space for it. However, the kernel does not immediately back that space with physical memory. Physical pages are only consumed when the process actually touches the memory.
The kernel relies on the assumption that not all allocated memory will be actively used at the same time. Usually, this assumption holds. When it doesn’t, the kernel invokes the OOM killer to free memory by terminating a process.<br>For most processes, handling an OOM kill is simple: the process restarts, reconnects, and picks up where it left off. PostgreSQL is different.
PostgreSQL's postmaster (its main supervisor process) forks a backend process for each connection. These backends share memory segments that hold shared buffers, WAL buffers, lock tables, and other shared state. The OOM killer doesn't understand this architecture. It simply picks a process based on an heuristic (usually the process that uses the most memory) and terminates it. If that backend was modifying a shared memory segment, the segment may be left in an inconsistent state. Shared memory has no transactional guarantees at the OS level. A half-written page in shared buffers means silent data corruption.
PostgreSQL's postmaster knows this. When it detects that any of its child processes has been killed, it assumes the worst: shared memory may be corrupted. When shared memory is corrupted, there...