Redis OOM Command Not Allowed: Check `maxmemory` and Eviction Candidates First
Dev
Last updated on

Redis OOM Command Not Allowed: Check `maxmemory` and Eviction Candidates First


When Redis returns OOM command not allowed when used memory > 'maxmemory', the common mistake is to interpret it as total host memory collapse. In practice, Redis is usually saying something narrower: under the current memory policy, this memory-growing command cannot continue.

The short version is simple: check maxmemory, maxmemory-policy, and the real eviction candidate set first. Most incidents are policy-and-workload problems before they are hardware problems.


When this guide is the right fit

Start here if one of these sounds familiar:

  • Redis rejects writes with the OOM message even though the host still has RAM
  • cache writes fail, but reads still work
  • the team expected eviction, but Redis is rejecting commands instead
  • volatile-* policy is configured, yet memory-growing writes still fail
  • a small number of keys or one write path seems to trigger the incident suddenly

What to check in the first 10 minutes

These commands are enough for the first pass:

redis-cli INFO memory
redis-cli INFO stats
redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy
redis-cli --bigkeys

If one key family already looks suspicious, add:

redis-cli MEMORY USAGE my:key SAMPLES 0
redis-cli TTL my:key

At this stage, answer only four questions:

  • did Redis hit its configured maxmemory ceiling?
  • what exact policy is active under pressure?
  • does Redis actually have eligible eviction candidates?
  • are big keys, missing TTLs, or persistence buffers amplifying the problem?

What this OOM message actually means

Redis eviction docs say that when the cache exceeds maxmemory, Redis enforces the selected eviction policy. Under noeviction, Redis does not evict keys and instead returns an error for commands that add new data.

So the OOM message usually means:

  • memory pressure is real at the Redis policy boundary
  • the command needs extra memory
  • the active policy cannot free suitable keys fast enough, or at all

That is a policy failure at the command boundary, not automatically proof that the machine itself has no RAM left.

Reads can still work while writes fail

Redis docs are explicit about one important operational detail: under noeviction, commands that only read existing data still work normally.

That is why an incident often looks like this:

  • cache reads still succeed
  • health checks still pass
  • memory-growing writes fail with OOM

This pattern often confuses teams into looking at client bugs first, when the more useful question is what Redis is allowed to do under pressure.

maxmemory and maxmemory-policy are the first real branch

These two settings explain a surprising amount:

Setting patternWhat it usually meansBetter next step
noevictionmemory-growing writes will fail at the limitinspect write path and capacity planning
allkeys-*Redis may evict from the whole datasetinspect whether eviction churn matches access pattern
volatile-*only keys with TTL are eligibleinspect whether TTL coverage is real, not assumed
volatile-ttlshort remaining TTL keys are preferredinspect whether key expiry design matches workload

If the team expected “old cache keys can always disappear,” but the configured policy does not actually allow that, the incident becomes much easier to explain.

volatile-* can behave like noeviction

Redis docs make this point very clearly: the volatile-* policies behave like noeviction if no keys have an associated expiration.

That means a cache can fail like this:

  • the team chose a volatile-* policy
  • later write paths created many persistent keys
  • Redis reached maxmemory
  • Redis had almost nothing it was allowed to evict

This is one of the most common reasons an OOM incident feels surprising.

Missing TTL is often the real bug, not memory itself

Once a key loses its expiration, it is no longer a candidate for volatile-* eviction. That connects this incident directly to Redis Keys Not Expiring.

This is the pattern to watch for:

  • the app assumes the data is cache-like
  • later writes cleared TTL or never set it
  • the key became persistent
  • Redis ran out of legal eviction candidates

Big commands can temporarily overshoot the limit

Redis eviction docs also note that a command adding a lot of data can exceed the memory limit by a large amount temporarily before eviction catches up.

That matters for incidents triggered by:

  • large set or sorted-set writes
  • batch cache population
  • one unexpectedly large value

So “the last command was small” is not enough. The recent write shape matters too.

Replication and persistence buffers make the memory picture wider

Redis docs explain that replication and AOF buffers are not counted toward maxmemory eviction checks. Redis exposes this as mem_not_counted_for_evict in INFO memory.

That leads to an important operational split:

  • Redis can enforce maxmemory correctly for key eviction
  • the host can still feel tighter than the dataset alone suggests
  • write pressure plus replica or AOF buffers can make the incident look worse

If mem_not_counted_for_evict is meaningful, capacity planning should include it instead of looking only at the dataset.

used_memory_dataset helps separate data from overhead

INFO memory reports used_memory_dataset as dataset bytes and mem_not_counted_for_evict as memory outside eviction accounting for replica and AOF buffers.

That makes the first split easier:

  • dataset is genuinely too large
  • key eligibility is wrong for the policy
  • operational buffers are making the node feel tighter

This is why Redis Memory Usage High is often the next useful guide.

Use --bigkeys and MEMORY USAGE to find the expensive path

Redis MEMORY USAGE key [SAMPLES count] reports the RAM cost of one key, and SAMPLES 0 checks all nested values for a fuller estimate.

That makes a strong pair with redis-cli --bigkeys:

  • identify structurally large keys
  • measure the actual cost of one suspicious key
  • check whether one feature area dominates memory unexpectedly

If one or two keys dominate the incident, the next stop is usually Redis Big Keys.

Common causes

1. noeviction under real pressure

Redis is doing exactly what the policy tells it to do.

2. volatile-* with weak TTL coverage

The team expected eviction, but the actual candidate pool is tiny.

3. Big keys or large batch writes

One write path adds more memory than the team expected.

4. Missing TTL on cache-like keys

Persistent keys crowd out the legal eviction set.

5. Replica or AOF buffers widen the pressure picture

mem_not_counted_for_evict makes the operational memory story larger than the dataset alone.

Common wrong starts

  • assuming host RAM exhaustion without checking maxmemory
  • changing application retries before checking the eviction policy
  • using volatile-* and assuming all cache keys still have TTL
  • increasing maxmemory before identifying big keys or TTL drift
  • ignoring mem_not_counted_for_evict on replicated or persisted instances

A practical debugging order

1. Check maxmemory and maxmemory-policy

This tells you what Redis is allowed to do under pressure.

2. Check whether eviction candidates really exist

With volatile-*, this is often the whole incident.

3. Check big keys and the actual cost of suspicious writes

This turns a vague memory story into a measured one.

4. Check mem_not_counted_for_evict

This explains why the node can feel tighter than the dataset alone suggests.

5. Decide whether the fix is policy, TTL hygiene, or capacity

Do not jump to one answer before this split is clear.

Checklist

  • I checked maxmemory
  • I checked maxmemory-policy
  • I confirmed whether eviction candidates actually exist
  • I inspected big keys or suspicious memory-heavy keys
  • I checked mem_not_counted_for_evict

FAQ

Q. Does this OOM message always mean the server has no RAM left?

No. It often means Redis reached its own maxmemory boundary and the active policy cannot free the right keys.

Q. Why do reads still work while writes fail?

Because under noeviction, read-only commands still work while memory-growing writes are rejected.

Q. Why can volatile-* still end in OOM?

Because it behaves like noeviction when no keys have an expiration.

Q. What is the fastest command pair for one suspicious key?

MEMORY USAGE key SAMPLES 0 and TTL key.

Sources:

Start Here

Continue with the core guides that pull steady search traffic.

Sponsored