How to Fix PostgreSQL Out-of-Memory (OOM) Crashes Under High Traffic Load

 How to Fix PostgreSQL Out-of-Memory (OOM) Crashes Under High Traffic Load

26 Oct 2026

Quick Summary: How Do You Stop the Linux OOM Killer From Terminating PostgreSQL?

To reduce PostgreSQL OOM kills, first identify which process consumed memory. Then review shared_buffers and work_mem, cap uncontrolled concurrency, add connection pooling where appropriate, and monitor memory pressure continuously. Test every configuration change under representative load before any production rollout.

1. The Production Nightmare:  Anatomy of a PostgreSQL OOM Crash

An out-of-memory (OOM) event happens when a process requests memory the system cannot provide. On Linux, the kernel may respond by invoking the OOM killer, which selects a process to terminate so the host can keep running. For teams searching for a PostgreSQL OOM killer fix, the first lesson is that the outcome depends on which process the kernel selects.

If the victim is a single backend, PostgreSQL logs that a server process was terminated by signal 9. Because a killed backend may have been touching shared memory, the postmaster typically terminates the other sessions and runs crash recovery before accepting connections again. If the postmaster itself is selected, the whole instance goes down. The kernel does not always choose the postmaster; it may pick an unrelated process, such as an application server or monitoring agent.

A Postgres out-of-memory production crash rarely has one cause. Common contributors include connection spikes that multiply backend processes, sorts and hash joins that allocate work_mem several times per query, parallel workers, maintenance and autovacuum jobs, extensions, and other services on the same host.

Also separate a PostgreSQL-level error from a kernel kill. An ERROR: out of memory message with a failed-request detail means an allocation failed inside PostgreSQL and typically affects only that statement. A log entry about a process terminated by signal 9, paired with kernel messages, points to the OOM killer. Collect this evidence before changing anything:

  • Kernel logs:dmesg -T or journalctl -k, noting the victim process, its memory footprint, and any cgroup involved.
  • PostgreSQL logs: signal 9 terminations, out-of-memory errors, crash-recovery messages, and temp-file spills (log_temp_files).
  • Memory metrics: per-process proportional set size (PSS), free memory, swap activity, and page cache trends around the incident.
  • Activity:pg_stat_activity for connection counts and long-running queries; on PostgreSQL 14 and later, pg_log_backend_memory_contexts() to log a suspect backend's memory use.
  • Query behavior:EXPLAIN (ANALYZE, BUFFERS) for large sorts, hashes, and parallel plans.

dmesg -T | grep -i -E 'out of memory|killed process'

journalctl -k --since '2 hours ago' | grep -i oom

2. Default PostgreSQL Configuration vs. Production Memory Hardening

PostgreSQL defaults favor safe startup on modest hardware, not every production workload, but they are not automatically unsafe. Treat the right-hand column as a review checklist, not a set of fixed values.

Setting or area

Why it matters

Production tuning approach

shared_buffers

Shared cache allocated at startup; the default is 128 MB. Oversizing leaves less memory for backends and the operating system.

About 25% of RAM is a common starting point on a dedicated server; then validate against workload, OS needs, and co-located services.

work_mem

A per-operation limit for sorts and hashes, not a per-connection budget. The default is 4 MB; operations and sessions multiply.

Estimate from peak concurrency. Raise it per role or query for known heavy jobs instead of globally.

max_connections

Each connection is a backend process with its own memory. The default is 100.

No universal number. Set it from workload and pooling design; do not use it as a substitute for query tuning.

Connection pooling (PgBouncer)

Lets many client connections share fewer server connections.

Choose pool mode and sizes from query duration and capacity, and test application compatibility.

Linux memory overcommit

Controls how the kernel accounts for memory promises; strict mode makes allocations fail earlier.

Review vm.overcommit_memory and the ratio against RAM, swap, and huge pages. Test; do not assume.

OOM selection and recovery

Determines which process is killed and how quickly service returns.

Review oom_score_adj, systemd or container limits, and restart policy. Rehearse recovery.

3. The Four-Step Engineering Blueprint to Reduce OOM Crashes

This framework addresses how to prevent PostgreSQL OOM crashes under high concurrency in 2026. Each step needs validation against your PostgreSQL major version, workload, and host.

Step 1: Calculate a Safe work_mem Strategy

Any Postgres work_mem vs shared_buffers memory tuning guide should start with one distinction: shared_buffers is allocated once and shared, while work_mem is a limit applied to each sort, hash table, or similar operation. One query can contain several such operations, parallel workers can each use their own allowance, and every active session can do this simultaneously. Hash operations may also exceed work_mem through hash_mem_multiplier, whose default differs across releases.

A conservative planning estimate, not a guarantee:

available = RAM - OS and co-located services - shared_buffers

            - backend overhead - maintenance/autovacuum allowance

work_mem ceiling ~ available / (peak concurrent active queries

                    x memory-intensive operations per query, incl. parallel workers)

Illustration under stated assumptions: a dedicated 64 GB host reserves 4 GB for the OS, 16 GB for shared_buffers, 4 GB for backend overhead, and 4 GB for maintenance work, leaving 36 GB. With an assumed 100 concurrent active queries and four memory-intensive operations each, 400 operations share that pool, a ceiling near 92 MB. Applying a 50% safety margin suggests testing around 32 to 48 MB. These figures are not recommendations for your server.

Validate under representative peak concurrency rather than choosing a value from RAM alone, and watch temp-file spills, since too low a value shifts work to disk. Raise work_mem per role, database, or transaction for known reporting jobs instead of globally.

Step 2: Control Connection Concurrency With PgBouncer

Every PostgreSQL connection is a backend process, and many simultaneously active backends increase memory pressure and contention. Per-backend memory varies with queries, extensions, and cached data, so measure PSS on your own system. As a hypothetical, 1,000 backends averaging 10 MB would hold roughly 10 GB before any work_mem allocations; your average may differ widely.

PgBouncer can help when applications open many mostly idle connections, because it separates client connections from server connections. In session pooling, a server connection is assigned for the client's session. In transaction pooling, it is assigned only for the duration of a transaction, which improves reuse but can break session-dependent behavior such as session-level settings, advisory locks, LISTEN/NOTIFY, and, depending on version and configuration, prepared statements. Test the application in the chosen mode before rollout.

Size pools from query duration, workload, and database capacity rather than a target ratio. A hypothetical pool of 100 server connections serving thousands of clients may suit short transactions and fail for long-running ones; no reduction is guaranteed.

Step 3: Review Linux Memory Management and Host Capacity

Before touching kernel settings, document physical RAM, swap, co-located processes, shared memory and huge page use, and observed allocation patterns. PostgreSQL's documentation notes that default heuristic overcommit can make the OOM killer more likely, and that vm.overcommit_memory = 2 makes the kernel refuse allocations beyond a commit limit instead. That limit derives from swap plus a share of RAM set by vm.overcommit_ratio (or vm.overcommit_kbytes).

Strict mode is a trade-off, not an automatic fix. Allocation failures can surface in PostgreSQL as errors, but other processes may handle them poorly. It does not guarantee graceful SQL errors or eliminate kernel OOM events, and a badly calculated ratio can cause failures at modest actual usage. Example for review only, never a universal recipe; test it and keep a rollback plan:

# Inspect current state first

sysctl vm.overcommit_memory vm.overcommit_ratio

grep -i commit /proc/meminfo

# Candidate settings, derived from your host (not copy-paste values):

# vm.overcommit_memory = 2

# vm.overcommit_ratio  = <calculated from RAM, swap, huge pages>

Step 4: Improve OOM Recovery and Service Resilience

Evaluate recovery as carefully as prevention:

  • Victim selection: confirm from kernel logs which process was chosen and whether a container or systemd cgroup limit triggered the kill.
  • Supervision and recovery: review restart behavior, crash-recovery duration, and failover design against your availability requirements.
  • Monitoring and alerting: track memory pressure, swap activity, backend counts, and temp-file growth so warnings arrive before kills.
  • Limits: MemoryMax or MemoryHigh in systemd units, and container memory limits, can contain a runaway process but move the kill boundary, so leave headroom.

Be cautious with oom_score_adj = -1000 on the postmaster. It exempts that process from OOM selection, so the kernel may kill other critical processes or leave the host under severe memory pressure. PostgreSQL's documentation describes protecting the postmaster while letting child backends return to normal scores through startup-script environment variables; evaluate that pattern against recovery behavior, service management, and host stability rather than applying it as a default. Rehearse recovery in a test environment and maintain a rollback plan before changing production service or kernel settings.

4. Frequently Asked Questions

Why does PostgreSQL crash with an OOM error even when shared_buffers is set low?

Because shared_buffers is only one part of total memory use. Each backend has its own overhead; every sort or hash operation can allocate up to work_mem (more for hashes when hash_mem_multiplier applies); parallel workers add their own allowances, and maintenance operations such as index builds and autovacuum use maintenance_work_mem. Extensions, the page cache, and other host services compete for the same RAM. Diagnose from kernel logs, PostgreSQL logs, and memory metrics rather than assuming a single cause.

Does adding swap space solve PostgreSQL Out-Of-Memory crashes?

Not by itself. Swap can add headroom and absorb short spikes, but it does not fix excessive allocations or uncontrolled concurrency; it only delays the point where memory runs out. Its effect on latency depends on the workload, the storage behind it, and how much active memory gets paged out. Treat swap as one element of a considered host-memory strategy alongside right-sized work_mem, connection control, and monitoring.

5. Resolve Database Crashes and Scale PostgreSQL With Senior DBAs

Reading logs is straightforward; finding the cause is harder. Experienced engineers correlate kernel messages, PostgreSQL logs, memory metrics, and query plans to determine whether the trigger is a connection storm, a memory-intensive plan, a configuration mismatch, or an extension or application leak. Teams seeking a PostgreSQL OOM killer fix or PostgreSQL memory leak troubleshooting services often benefit from outside eyes on production OOM events, high-concurrency workloads, and inefficient queries.

If you are weighing whether to hire a PostgreSQL performance tuning agency, look for evidence-based diagnosis rather than a one-size-fits-all configuration. NanoByte Technologies' custom database optimization services can cover execution-plan review, connection-pooling strategy, capacity planning, and memory monitoring. For growing platforms, PostgreSQL database scaling consulting addresses workload isolation and operational resilience, while high-traffic database architecture developers design for concurrency from the start. Teams that need hands-on depth can hire a senior PostgreSQL DBA through NanoByte for incident review and prevention planning. Every engagement begins with assessing your workload, and outcomes depend on your system.

Database Crashing Under High Load or Suffering From OOM Kills?

Unexpected database memory pressure can disrupt production and affect application reliability. NanoByte Technologies can help assess PostgreSQL memory usage, connection concurrency, query behavior, and scaling requirements to identify practical next steps.

Partner with NanoByte Technologies to assess your PostgreSQL performance and database scaling requirements.