DBRaven
Failure Mode · capacity

Memory Pressure and OOM Kill

critical

Summary

When total memory demand from a process or the entire host exceeds available physical RAM plus swap, the Linux OOM killer terminates one or more processes to reclaim memory, causing immediate connection loss, data corruption risk if in-flight writes are lost, and process restart overhead.

Description

The Linux OOM (Out-Of-Memory) killer is invoked when the kernel cannot satisfy a memory allocation request from any process and swap space is exhausted. The OOM killer selects a process to terminate based on an oom_score calculation (a function of memory usage, runtime, and /proc/PID/oom_adj). Database processes (PostgreSQL postmaster, Redis, MongoDB mongod) are large memory consumers and are frequently selected as OOM victims.

For PostgreSQL: when the postmaster process is OOM-killed, all client connections are severed immediately. The shared memory segment (shared_buffers) is deallocated. Dirty shared buffer pages that had not been checkpointed to disk are lost: these will be replayed from WAL on restart, but WAL replay may take minutes for a large shared_buffers. All active transactions are rolled back by the crash recovery process. Depending on crash recovery mode, the database may be unavailable for 1–10 minutes.

For Redis: if the Redis process is OOM-killed and persistence is disabled (save "" or appendonly no), all in-memory data is permanently lost. If appendonly yes is configured, the AOF file contains all committed writes but recovery requires replaying it: seconds to minutes depending on AOF size.

Memory pressure scenarios in PostgreSQL: 1. shared_buffers configured too large: shared_buffers = 16GB on a 16GB host

leaves 0GB for OS page cache, sort operations, and other processes.

2. Sort and hash operations exceeding work_mem: a complex query with 10 hash

joins at work_mem = 256MB can allocate 10 × 256MB = 2.5GB for a single query.

Multiply by concurrent queries.

3. Connection count × connection overhead: each PostgreSQL connection uses

5–10MB of memory (stack, local cache). 1,000 connections = 5–10GB.

4. Autovacuum workers with large scale: autovacuum on a very large table

with aggressive settings can consume hundreds of MB per worker.

Memory pressure builds gradually and is often ignored until the OOM event. The first signs are the kernel beginning to reclaim page cache aggressively (free -m shows available memory dropping to near 0) and swap utilisation growing. These are warning signals that OOM is approaching.

Characteristics

Propagationfan out
Time to detectThe OOM event itself is instantaneous and detectable immediately via kernel logs and process monitoring. Pre-OOM memory pressure is detectable 5–30 minutes before the event with available memory monitoring and swap utilisation trending. Without proactive memory monitoring, OOM events are detected only when applications begin reporting connection errors.
Blast radiusAn OOM kill of the database process immediately severs all client connections. All applications that depend on the database receive connection errors. For PostgreSQL, in-flight transactions that had not committed are rolled back via crash recovery. For Redis without persistence, all cached data is lost, causing a full cache miss storm on recovery. If the OOM condition is not addressed, the process will be OOM-killed again shortly after restarting.

Triggers

  • ·shared_buffers set to >30% of total RAM without accounting for other memory consumers
  • ·work_mem × max_connections × average_concurrent_queries exceeds available RAM
  • ·Connection count spike (autoscaling without connection pooling) × per-connection overhead exceeds RAM
  • ·Autovacuum workers running concurrently on large tables with high maintenance_work_mem
  • ·Application memory leak causing gradual growth until host-level memory exhaustion

Detection Signals

memory pressuredisk saturationerror rate spikelog errors

Mitigation Strategies

Set shared_buffers to 25% of available RAM, not total RAMpreventscomplexity: low

PostgreSQL recommendation: shared_buffers = 25% of RAM. Leave 75% for OS page cache, work_mem allocations, and other processes. On a 32GB host: shared_buffers = 8GB. This is not the aggressive setting some guides recommend (40–50%): those figures assume the database is the only process on the host.

Set work_mem based on max_connections, not arbitrary large valuepreventscomplexity: medium

work_mem × concurrent_complex_queries_per_connection × max_connections must fit within available RAM after shared_buffers. Formula: work_mem = (available_RAM - shared_buffers) / (max_connections × 0.1). For 32GB host with 8GB shared_buffers and 200 connections: work_mem = 24GB / 20 = 1.2GB. Override per-query for known-expensive analytical queries.

Enable HugeTLB and use memory overcommit controlspreventscomplexity: medium

Set vm.overcommit_memory = 2 and vm.overcommit_ratio = 80 to prevent the kernel from committing more virtual memory than 80% of physical RAM. Processes that attempt to allocate beyond this will fail at allocation time (ENOMEM) rather than being OOM-killed at access time. PostgreSQL handles this gracefully.

Set container memory limits and database maxmemory below host RAMpreventscomplexity: low

In containerised environments (Kubernetes, Docker), set memory limits for the database container. Redis respects maxmemory configuration. PostgreSQL requires container-level limits combined with shared_buffers tuning. Prevents the database from consuming host memory to the OOM boundary.

Recovery Steps

  1. 1.Confirm OOM event: check dmesg for OOM killer log entries and identify victim process
  2. 2.If database process was killed and has not restarted automatically: start the process
  3. 3.Monitor crash recovery: PostgreSQL will replay WAL from last checkpoint (check logs for progress)
  4. 4.Reduce memory pressure before reconnecting application: reduce max_connections, reduce shared_buffers if they were the cause
  5. 5.If Redis was OOM-killed without persistence: application cache is empty; implement thundering herd prevention before re-enabling traffic
  6. 6.Post-recovery: audit memory configuration against RAM budget and implement memory monitoring with pre-OOM alerting

Estimated recovery time: 30 seconds to 5 minutes for process restart. WAL crash recovery may add 1–10 minutes depending on shared_buffers size and checkpoint age. Redis AOF replay: seconds to minutes. Application connection pool re-establishment: 10–60 seconds.

Affected Systems

Patterns

connection poolingcache asidematerialized viewwrite behind cache

Technologies

postgresqlredismongodbelasticsearch

Basis

Precisely specified kernel-level failure mode with observable pre-conditions; PostgreSQL and Redis memory configuration parameters are exact and well-documented

Run This Failure

Blast radius analysis for this failure mode within each scenario that carries it.

Related Architecture Knowledge

Inbound: affects this entity

Vulnerable ToWorkload
ai embedding lookup
Grounded

AI embedding lookup workloads require the entire vector index to reside in RAM for acceptable latency. When the index size grows beyond available memory, the OS begins paging the HNSW graph to disk, causing query latency to degrade from milliseconds to seconds and eventually OOM-killing the process.

Tradeoffs

  • ·Quantization reduces memory by 4-8x but degrades recall slightly: evaluate recall impact before deploying
  • ·IVFFlat has lower memory than HNSW but requires training (cluster computation) when adding new vectors
  • ·Horizontal scaling (shard vectors across instances) reduces per-node memory at the cost of scatter-gather query overhead
Full relationship →

Used In Architecture Scenarios

AI Retrieval-Augmented Generation Platformhigh

AI / RAG Application

A Retrieval-Augmented Generation (RAG) architecture that combines vector similarity search for semantic document retrieval with relational metadata filtering, using PostgreSQL with pgvector as the unified store for both embeddings and structured data. Redis provides a semantic cache to avoid redundant embedding model inference and reduce vector index query load for repeated or similar queries. Kafka manages the asynchronous embedding generation pipeline that keeps the vector index current as source documents are added or updated.

Geospatial Tracking Platformhigh

Realtime Collaboration

A real-time location tracking platform for moving entities: vehicles, delivery couriers, field workers, and assets: receiving position updates at 1–30 second intervals from thousands of simultaneously tracked objects. Redis geospatial indexes (GEOADD / GEOSEARCH) serve sub-10ms proximity queries against the live position surface; PostgreSQL stores durable entity metadata and historical location records; TimescaleDB stores high-frequency time-series location data with automatic hypertable chunking and retention policies; Kafka streams location events to downstream consumers (dispatch systems, customer tracking apps, analytics pipelines). Geofence evaluation runs at ingestion time: each incoming position update is tested against active geofences for the entity's region, and geofence entry/exit events are emitted as Kafka messages to downstream consumers.