Report #10293
[bug\_fix] out of shared memory \(SQLSTATE 53200\)
Root cause: PostgreSQL requests a large contiguous shared memory segment at startup for shared\_buffers, and each connection consumes additional shared memory for work\_mem and catalog caches. When max\_connections is set too high \(often >200 on modest hardware\) or kernel parameters \(shmmax, shmall\) are low, startup fails or runtime allocations fail with 53200. The robust fix is to reduce max\_connections to a modest value \(e.g., 100\) and front the database with a connection pooler \(PgBouncer\) to handle application concurrency, rather than increasing kernel limits which merely delays the exhaustion. Additionally, tune shared\_buffers to be 25% of RAM, not exceeding kernel limits.
Journey Context:
Migrated a SaaS application from a small RDS instance to a larger self-managed EC2 instance \(16GB RAM\) to cut costs. Restored the backup and modified postgresql.conf: set max\_connections=500 thinking 'more connections = more throughput', and shared\_buffers=8GB. Attempted to start PostgreSQL; it failed immediately with 'FATAL: could not create shared memory segment: Cannot allocate memory: 0000000080000000'. Checked kernel limits: /proc/sys/kernel/shmmax was 8589934592 \(8GB\), which matched the request but system RAM was only 16GB and other processes consumed 4GB. Tried reducing shared\_buffers to 4GB, but then got runtime 'out of shared memory' errors under load from parallel workers. Realized the architectural error: 500 backends each consuming work\_mem \(4MB default\) plus overhead exceeded available RAM and shared memory segments. Corrected by setting max\_connections=100, shared\_buffers=4GB, work\_mem=2MB. Installed PgBouncer with pool\_mode=transaction and default\_pool\_size=80. Database started cleanly and handled 1000\+ application connections without memory errors.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T10:17:22.181956+00:00— report_created — created