Skip to content
ohsudo, Home
Databases

Redis "OOM command not allowed when used memory > maxmemory": choose what to do when full

Fix Redis "OOM command not allowed when used memory > maxmemory": read INFO memory, choose an eviction policy, find big keys, set expiry, and raise maxmemory with care.

Intermediate3 min readApplies to Redis 6+ · Valkey · redis-cli · Docker

by OhSudo ·

Not sure this is your cause?Find it step by step: Can't connect to the database →Find it step by step: Disk full or out of memory →

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

Redis has reached its memory limit, and its current policy is to refuse new writes. Reads still work, and nothing is lost. So the real question is what should happen when Redis is full? That depends on whether it’s a cache, where old data can go, or a store, where it can’t.

TL;DR

Terminal window
redis-cli INFO memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy'
redis-cli --bigkeys

For a cache, let Redis throw out old keys:

Terminal window
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG REWRITE

1. Look at the numbers

Terminal window
redis-cli INFO memory | grep -E 'used_memory_human|used_memory_peak_human|maxmemory_human|maxmemory_policy|mem_fragmentation_ratio'
used_memory_human:2.00G
used_memory_peak_human:2.00G
maxmemory_human:2.00G
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.08

noeviction is the default, and it’s what produces this error: when full, refuse writes. Now see what’s taking the space.

2. Choose a policy

Policy When full Good for
noeviction Refuses writes Data you can’t lose, such as queues or sessions
allkeys-lru Removes the least recently used key A pure cache: the usual choice
allkeys-lfu Removes the least often used key A cache with some very popular keys
volatile-lru Same, only among keys with an expiry A mix, if your cache keys have a TTL
volatile-ttl Removes what’s closest to expiring A mix as well
Terminal window
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG REWRITE

CONFIG REWRITE keeps it across restarts. In Docker, or with a read-only config, put it in the redis-server command line or redis.conf instead.

One trap: with volatile-*, if no key has an expiry then nothing can be removed, and you get this same error. And if Redis holds queues or job data, such as with Sidekiq or BullMQ, don’t use allkeys-*, as it would silently delete your jobs. Those need noeviction, and more memory or fewer jobs.

3. Find what’s using the memory

Terminal window
redis-cli --bigkeys
redis-cli --memkeys

Both scan safely, without blocking the server. For one key:

Terminal window
redis-cli MEMORY USAGE session:12345
redis-cli TYPE session:12345
redis-cli TTL session:12345

TTL returns -1 if a key never expires, the most common cause of slow growth. To count keys by prefix, sample with SCAN, and never run KEYS * on a busy server, which blocks everything until it finishes:

Terminal window
redis-cli --scan --pattern 'session:*' | wc -l

4. Set expiry times

Code that writes without a TTL makes Redis grow until it’s full. Set one when you write:

SET session:12345 "data" EX 3600
await redis.set(`session:${id}`, data, { EX: 3600 });

To clean up old keys in batches, without blocking:

Terminal window
redis-cli --scan --pattern 'tmp:*' | xargs -r -n 500 redis-cli UNLINK

UNLINK frees the memory in the background, where DEL on a big key can stall the server.

5. Raise the limit, carefully

Terminal window
redis-cli CONFIG SET maxmemory 4gb
redis-cli CONFIG REWRITE

Check first what the machine has, with free -h, and leave room. Saving to disk forks the process, and on a busy server, it can use a lot of extra memory for a time. A limit of maxmemory too close to the machine’s total invites the OOM killer, which ends Redis itself. In a container, keep it below the memory limit too, or you get an exit code 137.

6. Memory used, but not by your data

If used_memory is low, and the process is large, look at mem_fragmentation_ratio. Well above 1.5 means fragmentation:

Terminal window
redis-cli CONFIG SET activedefrag yes

Output buffers may also take a lot: replicas falling behind, or clients that subscribe and don’t read. CLIENT LIST shows each client’s omem, and client-output-buffer-limit sets the limits.

If you see this on a replica, it follows its primary’s data, so the primary is what needs the attention.

Warning

Setting maxmemory 0 means “no limit”, and it makes this error go away. Redis then grows until the machine runs out, and the kernel kills it, which is worse. Also check that memory is actually what’s wrong, before deleting things, and take a backup first if that data matters.

Shell, we have a problem!

Similar, but different: MISCONF Redis is configured to save RDB snapshots means it can’t write to disk: see that article. NOAUTH means you need a password. READONLY You can't write against a read only replica means you connected to a replica. The Port Lookup explains why 6379 should stay private.

Found this useful? Share it.

Found a mistake? Let us know at contact@ohsudo.com.

Tools

Try it yourself

Articles

Related articles