/인프라/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

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 commandSET, 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 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.

(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 the 8 maxmemory-policy options

Picking the policy that matches your situation is the key.

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◎ (increasingly recommended)
volatile-lruLRU among keys that have a TTLTTL keys only
volatile-lfuLFU among keys that have a TTLTTL 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

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

③ Effective shortage due to memory fragmentation

  • Symptom: used_memory still has headroom, but you get OOM or OS swap
  • Cause: Frequent key create/delete fragments jemalloc; 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

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+).

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, and adoption of frequency-based allkeys-lfu is growing. As a side note, after the 2024–2025 license change (RSAL → AGPL) some teams are moving to Valkey, but maxmemory behavior and commands are the same, so this guide applies as-is.

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 I still get OOM. Why? A. 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.

확인 정보
✦ ✦ ✦
편집 검토 · Editorial Review

Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

편집 책임 · Nodelog 기술 편집팀·발행 · ·업데이트 ·
관련 공식 문서Redis 공식 문서

Comments

Be the first to comment.