Fix PostgreSQL: “Cannot allocate memory” When Forking a New Connection

The Error

psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed:
could not fork new process for connection: Cannot allocate memory

This error is misleading. It usually does not mean your server is out of RAM in the way people expect. It means that when PostgreSQL’s postmaster tried to fork() a new backend process to serve your connection, the kernel refused the request with ENOMEM. The refusal can come from actual memory pressure, from kernel overcommit accounting, or from per-process resource limits. Understanding which one is the cause is the whole job.


Step 1: Confirm the Server Is Actually Up

Because the socket connection is being refused at fork time, PostgreSQL itself is often still running. Verify this before you assume the database has crashed.

sudo systemctl status postgresql-14
ps -ef | grep postgres | head

If the postmaster process is alive but new connections fail, you are dealing with a resource problem at connection time rather than a database outage. This matters because restarting PostgreSQL may temporarily clear the symptom without fixing the root cause.


Step 2: Check Real Memory and Swap

Look at how much memory and swap are genuinely available on the host.

free -h
cat /proc/meminfo | grep -E 'MemFree|MemAvailable|Commit|Swap'

If MemAvailable is very low and SwapFree is near zero, the machine is under genuine memory pressure. On a database server this is frequently caused by too many concurrent backends, an oversized shared_buffers or work_mem, or another process on the box consuming RAM. Each PostgreSQL connection is a separate OS process and can consume several megabytes or more, so a connection spike multiplies quickly.


Step 3: Investigate Memory Overcommit Settings

This is the most common hidden cause. Linux decides whether to grant a fork() based on its overcommit policy, and a strict policy will reject forks even when free RAM appears available.

cat /proc/sys/vm/overcommit_memory
cat /proc/sys/vm/overcommit_ratio

A value of 2 for overcommit_memory means strict accounting: the kernel will only allow allocations up to swap + RAM * overcommit_ratio / 100. On a server with little or no swap and a low ratio, a busy PostgreSQL instance can hit this ceiling and every new fork fails with Cannot allocate memory, even though free -h shows headroom. The PostgreSQL project generally recommends either overcommit_memory = 2 with a carefully tuned ratio and adequate swap, or leaving it at the default 0. If you are hitting fork failures under strict mode, raising the ratio or adding swap usually resolves it:

# Temporary
sudo sysctl -w vm.overcommit_ratio=80

# Persistent
echo 'vm.overcommit_ratio = 80' | sudo tee -a /etc/sysctl.d/99-postgres.conf
sudo sysctl --system

Step 4: Check Per-Process and cgroup Limits

If the host has plenty of memory but only the postgres user is affected, the constraint is likely a resource limit rather than a system-wide shortage.

Inspect the limits applied to the running postmaster:

cat /proc/$(pgrep -o -u postgres postgres)/limits

Pay attention to Max processes (RLIMIT_NPROC) and Max address space (RLIMIT_AS). A low nproc cap will block new backends once the process count is reached, and the kernel reports this as an allocation failure. On systemd-managed servers, the service unit can also impose TasksMax, MemoryMax, or MemoryHigh through a cgroup:

See also: Mastering the Linux Command Line — Your Complete Free Training Guide

systemctl show postgresql-14 | grep -E 'TasksMax|MemoryMax|MemoryHigh|LimitNPROC'

If TasksMax is set too low, PostgreSQL cannot spawn enough backends. Raise it with a drop-in override:

sudo systemctl edit postgresql-14
[Service]
TasksMax=infinity
LimitNPROC=infinity

Then reload and restart:

sudo systemctl daemon-reload
sudo systemctl restart postgresql-14

Step 5: Look for a Connection Leak or Storm

Even with correct kernel settings, an application that opens connections without closing them will eventually exhaust every limit you configure. Check how many backends currently exist and where they come from.

SELECT count(*) FROM pg_stat_activity;
SELECT client_addr, state, count(*)
FROM pg_stat_activity
GROUP BY client_addr, state
ORDER BY count(*) DESC;

If you see hundreds of idle connections, the real fix is on the client side or in front of the database. Introducing a pooler such as PgBouncer dramatically reduces the number of OS processes PostgreSQL must fork, which both resolves the memory error and improves overall stability.


Step 6: Review Recent System Hardening Changes

Security hardening can quietly introduce this failure. STIG-style remediation often sets kernel.core_pattern, tightens sysctl values, restricts services through systemd cgroups, or lowers process limits. If the error appeared right after a hardening playbook ran, compare the current kernel and limit settings against a known-good baseline, and specifically re-check the vm.overcommit_* values and any TasksMax/LimitNPROC constraints introduced by new unit-file drop-ins. A change intended to constrain a general-purpose host can be too aggressive for a database that legitimately needs many processes.


Step 7: Check the Kernel Log for the Real Reason

Finally, confirm your diagnosis against what the kernel actually recorded.

sudo dmesg -T | grep -Ei 'oom|fork|memory' | tail -20
sudo journalctl -u postgresql-14 --since "1 hour ago"

If the OOM killer has been active, you will see it here and the answer is genuine memory pressure that needs capacity or tuning changes. If there is no OOM activity but forks are still failing, the cause is almost certainly overcommit accounting or a process/cgroup limit from the earlier steps.


Summary of the Diagnostic Path

The fastest way to resolve this error is to work from the outside in: confirm the server is still running, check whether memory is genuinely exhausted, then rule out the two most common silent culprits — Linux memory overcommit accounting (vm.overcommit_memory / vm.overcommit_ratio) and per-process or cgroup limits (RLIMIT_NPROC, TasksMax). In most production cases the RAM is fine and the real fix is either loosening an overly strict overcommit policy, raising the process limits imposed on the postgres service, or putting a connection pooler in front of the database to stop a connection storm from ever reaching the fork limit.

Avatar photo
David Cao

David is a Cloud & DevOps Enthusiast. He has years of experience as a Linux engineer. He had working experience in AMD, EMC. He likes Linux, Python, bash, and more. He is a technical blogger and a Software Engineer. He enjoys sharing his learning and contributing to open-source.

Articles: 675

Leave a Reply

Your email address will not be published. Required fields are marked *