Home/Infrastructure/Redis OOM Error (used memory > maxmemory): A 5-Minute Emergency Fix Guide
InfrastructureRedis OOMmaxmemory

Redis OOM Error (used memory > maxmemory): A 5-Minute Emergency Fix Guide

Step-by-step fix for the Redis "OOM command not allowed when used memory > maxmemory" error—from INFO memory diagnosis to raising maxmemory, enabling allkeys-lru eviction, and preventing recurrence with TTLs—using copy-paste commands.

Redis OOM Error (used memory > maxmemory): A 5-Minute Emergency Fix Guide
Contents
  1. 1. Assess the Situation in 30 Seconds: How to Read INFO memory
  2. 2. Immediate Recovery: Adjusting maxmemory and Choosing a Policy
  3. 3. Root-Cause Diagnosis: Five Scenarios That Trigger OOM
  4. 4. Recurrence-Prevention Checklist
  5. References: Official docs
  6. FAQ
  7. Sources · checked 2026-10-04

Redis OOM Error (used memory > maxmemory): A Complete 5-Minute Emergency Fix Guide

You haven't even deployed, but suddenly production logs start getting plastered with this message:

CODE
(error) OOM command not allowed when used memory > 'maxmemory'.

Reads still work, but every write command—SET, INCR, LPUSH, and the like—is rejected. If you use Redis as a session store or cache, this goes straight to a service outage. This post puts emergency treatment first and root-cause analysis second for anyone who is in an incident right now. Follow the roadmap below and you can restore writes in five minutes.

CODE
[1] Assess the situation with INFO memory (30 seconds)
[2] Raise maxmemory or change the eviction policy for immediate recovery (1 minute)
[3] Persist with CONFIG REWRITE (10 seconds)
[4] Prevent recurrence with TTLs and monitoring (afterward)

1. Assess the Situation in 30 Seconds: How to Read INFO memory

First, you need to see what state Redis is in right now.

Bash
redis-cli INFO memory
CODE
# Memory
used_memory:2147483648
used_memory_human:2.00G
used_memory_rss:2415919104
used_memory_rss_human:2.25G
maxmemory:2147483648
maxmemory_human:2.00G
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.12
mem_allocator:jemalloc-5.3.0

Look at just these four key metrics.

MetricMeaningHow to interpret
used_memoryMemory Redis is using logicallyDanger if close to or at maxmemory
used_memory_rssPhysical memory (RSS) actually occupied by the OSFragmentation if much larger than used_memory
mem_fragmentation_ratiorss ÷ used_memory1.0–1.4 normal / ≥1.5 fragmentation / <1.0 swap suspected
maxmemory_policyBehavior when the limit is hitnoeviction is the direct cause of write rejections

In the example above, used_memory == maxmemory and the policy is noeviction. In other words, this is the classic case: memory is full and there is no eviction policy, so writes are refused.

These helper commands are also worth knowing.

Bash
redis-cli MEMORY DOCTOR          # Redis itself prints a diagnostic comment
redis-cli MEMORY STATS           # detailed breakdown: peak.allocated, dataset.bytes, overhead.total, etc.
redis-cli --memkeys              # sample the keys using the most memory (redis-cli 6.2+)
redis-cli MEMORY USAGE mykey     # Bytes occupied by a specific key

2. Immediate Recovery: Adjusting maxmemory and Choosing a Policy

You are in one of two situations: (A) you can give it more memory, or (B) it is a cache, so dropping some keys is acceptable.

(A) If you have spare RAM, just raise the limit

If the server has spare RAM, raise maxmemory with no downtime.

Bash
redis-cli CONFIG SET maxmemory 4gb

This command takes effect immediately, and writes start working again right after.

💡 Containers: In Docker/Kubernetes, if maxmemory is left at 0 (the default; unlimited on 64-bit), Redis never raises this OOM error and keeps using memory until it hits the container memory limit, at which point the kernel OOM-kills the container. The symptom is completely different, so in containers set maxmemory explicitly and well below the limit (leave headroom for fork and buffers).

(B) If it is a pure cache, turn on an eviction policy

If you are using it as a cache but running with noeviction, that is the root problem. Switch to LRU so old keys are evicted automatically.

Bash
redis-cli CONFIG SET maxmemory-policy allkeys-lru

The moment you change the policy, the excess is evicted and writes recover immediately.

Comparison of maxmemory-policy options

Picking the policy that matches your situation is the key. Redis 8.6 added two LRM policies that only track writes, so the official docs now list 10 (Redis below 8.6 and Valkey have no LRM).

PolicyBehaviorTarget keysFor cacheFor sessions / persistence
noevictionReject writes (error) when the limit is hit—✕◎ (assuming you will scale memory)
allkeys-lruEvict the least recently used keysAll keys◎△
allkeys-lfuEvict the least frequently used keysAll keys◎△
allkeys-lrmEvict the least recently modified keys (Redis 8.6+)All keys○ (read-heavy)△
volatile-lruLRU among keys that have a TTLTTL keys only○○
volatile-lfuLFU among keys that have a TTLTTL keys only○○
volatile-lrmLRM among keys that have a TTL (Redis 8.6+)TTL keys only○○
allkeys-randomEvict at randomAll keys△✕
volatile-randomRandom among TTL keysTTL keys only△△
volatile-ttlPrefer keys closest to expiryTTL keys only○◎ (mixed TTL environment)

Selection guide

  • Pure cache: allkeys-lru, or allkeys-lfu if access-frequency skew is large
  • Mix of TTL keys and persistent keys: volatile-ttl or volatile-lru (keys without a TTL are protected)
  • Data loss is absolutely not allowed (sessions, queues, persistent storage): keep noeviction and scale memory. Do not try to ride it out with a policy change.

Persist the change

CONFIG SET is lost on restart. You must write it into the config file.

Bash
redis-cli CONFIG REWRITE

⚠️ CONFIG REWRITE has Redis rewrite redis.conf itself. Hand-written comments or layout can change, so if you manage config with Ansible, Helm, or similar, it's safer to edit the source config and redeploy.

Or edit redis.conf directly.

Config
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 5

maxmemory-samples is the sample size LRU/LFU uses when picking eviction candidates. The default of 5 is enough; you can raise it to 10 for more precision, but it uses more CPU.

3. Root-Cause Diagnosis: Five Scenarios That Trigger OOM

Once you have recovered, look at why it blew up. Organized as symptom → cause → how to confirm.

① Hit the maxmemory limit

  • Symptom: used_memory ≈ maxmemory, all writes rejected
  • Cause: Data growth exceeded allocated memory
  • Confirm: Compare the two values in INFO memory

② Policy is noeviction

  • Symptom: It is a cache, but keys are never dropped—only errors
  • Cause: The default noeviction was left in place for a cache
  • Confirm: CONFIG GET maxmemory-policy

③ Server memory shortage due to fragmentation

  • Symptom: no Redis OOM error, but the server swaps or the kernel OOM-kills Redis (the Redis OOM error is based on used_memory, so fragmentation alone never triggers it)
  • Cause: Frequent key create/delete fragments the allocator; RSS balloons and pressures OS memory
  • Confirm: mem_fragmentation_ratio of 1.5 or higher

④ fork (COW) pressure from RDB/AOF rewrite

  • Symptom: Memory spikes at BGSAVE/AOF rewrite time; fork-failure logs
  • Cause: On fork, Copy-On-Write duplicates parent memory if there are many writes. Worst case, instantaneous usage can double
  • Confirm: Log line Can't save in background: fork: Cannot allocate memory; rdb_last_bgsave_status in INFO persistence

⑤ Unbounded growth because keys have no TTL

  • Symptom: used_memory increases monotonically over time
  • Cause: It is a cache, but keys never expire and live forever
  • Confirm: redis-cli --bigkeys; watch the DBSIZE trend

Check for keys without a TTL with SCAN, not KEYS *. KEYS walks every key in one go and blocks other commands.

Bash
redis-cli --scan --pattern 'cache:*' --count 1000 | head -n 100   # cursor-based iteration
redis-cli TTL cache:user:99      # -1 means no expiry, -2 means the key doesn't exist

Field note: In production, the most commonly reported cause is #5—missing TTLs. A one-line code-review comment ("this SET is missing EX") would have prevented it, but it comes back as a 3 a.m. outage months later. Enforcing a TTL convention has a better cost-to-benefit ratio than policy tuning.

4. Recurrence-Prevention Checklist

Always put a TTL on cache keys. Set expiry at write time.

Bash
SET session:1234 "payload" EX 3600     # 1 hour
SETEX cache:user:99 600 "..."          # 10 minutes

Handle fragmentation. Turn on active defrag (Redis 4.0+). It only works when Redis is built with its bundled jemalloc, so first check that mem_allocator in INFO memory is jemalloc.

Bash
redis-cli CONFIG SET activedefrag yes

If fragmentation is severe and RSS will not come down, a restart as a last resort reclaims RSS (only after you have persisted the data).

Monitoring alerts. Use redis_exporter + Prometheus + Grafana and fire an alert at 80% memory usage.

YAML
groups:
  - name: redis-memory
    rules:
      - alert: RedisMemoryHigh
        expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.8
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Redis used_memory exceeded 80% of maxmemory"

That single alert buys you time to scale or clean up before you hit the limit.

Capacity-sizing tip. Take production used_memory_rss, multiply by 1.3–1.5 for fork/COW headroom, and size maxmemory and server RAM from that. Be more conservative if you use RDB.

In Redis 7.x you can also cap client buffers with maxmemory-clients. Per the official licenses page, Redis 7.2 and earlier are BSD-3, 7.4 moved to RSALv2/SSPLv1 (March 2024), and 8.0 added AGPLv3 as an option. Some teams moved to Valkey along the way; the eight maxmemory policies and commands in the Valkey docs match this guide (it has no LRM policies).

References: Official docs

The primary source for the behavior, settings, and errors covered in this post is the official documentation below. Check it for version-specific options and exact behavior.

FAQ

Q. If I change maxmemory-policy with CONFIG SET, are keys deleted immediately? A. If you switch to an evicting policy and used_memory already exceeds maxmemory, keys are removed immediately until you are back under the limit. If you have persistent data without TTLs, use volatile-* instead of allkeys-*, or raise maxmemory first.

Q. I changed it with CONFIG SET, but it reverts after a restart. A. CONFIG SET only changes the in-memory config. Run redis-cli CONFIG REWRITE to write it into redis.conf, or edit the config file yourself, so it survives a restart.

Q. used_memory still has headroom, but the server runs out of memory or gets OOM-killed. Why? A. Redis's OOM command not allowed error only fires when used_memory exceeds maxmemory, so this is memory pressure outside Redis. Check mem_fragmentation_ratio. If it is 1.5 or higher, fragmentation has ballooned RSS and the OS is short on memory. Enable activedefrag yes, or persist and restart to reclaim RSS.

Sources · checked 2026-10-04

Verification
✦ ✦ ✦
Sources and verification

Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us

This article has no recorded human check (date and scope) yet.

Published · ·Updated ·
Topic-related official docs (auto-linked · not per-claim sources)Redis documentation ↗

Comments

Be the first to comment.