The Redis error OOM command not allowed when used memory > 'maxmemory' means memory use has reached the maxmemory limit and the eviction policy can't free anything, so Redis rejects writes while still serving reads. On self-managed Redis the usual cause is the default noeviction policy; on Azure Cache for Redis and Azure Managed Redis it is usually the default volatile-lru policy combined with keys that have no TTL. You fix it by choosing an eviction policy that matches how you use Redis (often allkeys-lru for a pure cache), giving cache keys expirations, removing oversized keys, and leaving memory headroom or scaling up.
Who this is for and what you will have at the end
This guide is for developers and operators who see the OOM error in application logs on open-source Redis, Azure Cache for Redis or Azure Managed Redis.
At the end you will have:
- A clear diagnosis of why eviction isn't freeing memory.
- An eviction policy chosen deliberately for your workload.
- TTLs and key sizes under control.
- Alerts that warn you before memory runs out again.
Why Redis returns the OOM error
When a client runs a command that adds data, Redis compares memory use with maxmemory. If it is over the limit, Redis evicts keys according to maxmemory-policy until it is back under. If the policy doesn't allow eviction, or there's nothing eligible to evict, commands that would use more memory fail with the OOM error and read-only commands continue to work.
The available policies:
| Policy | What it evicts |
|---|---|
noeviction | Nothing; returns an error on commands that add data |
allkeys-lru | Least recently used keys, from all keys |
allkeys-lfu | Least frequently used keys, from all keys |
allkeys-random | Random keys, from all keys |
volatile-lru | Least recently used keys that have a TTL |
volatile-lfu | Least frequently used keys that have a TTL |
volatile-random | Random keys that have a TTL |
volatile-ttl | Keys with a TTL, shortest remaining TTL first |
Redis 8.6 also adds allkeys-lrm and volatile-lrm, which evict the least recently modified keys; check that your server version and managed service support them before relying on them.
The key rule: the volatile-* policies behave like noeviction if no keys have an expiration. That is the most common reason managed caches hit this error.
Defaults differ by platform
| Platform | Default maxmemory-policy | How maxmemory is set |
|---|---|---|
| Open-source Redis | noeviction | maxmemory in redis.conf or CONFIG SET; 0 means no limit on 64-bit systems |
| Azure Cache for Redis (Basic, Standard, Premium) | volatile-lru | Cache size, minus reserved memory |
| Azure Managed Redis | volatile-lru (VolatileLRU in the CLI) | SKU memory limit |
An open-source server with maxmemory 0 won't produce this error at all; it keeps growing until the operating system runs out of memory instead.
Microsoft has announced a retirement timeline for all Azure Cache for Redis SKUs and recommends moving to Azure Managed Redis, so treat the Azure Cache for Redis steps below as a fix for existing caches rather than a reason to deploy new ones.
Prerequisites
redis-clior another client that can runINFO, plus the host, port and credentials. Azure Managed Redis listens on port 10000 with TLS.- For Azure: write access to the cache resource (for example Contributor) and the Azure CLI. The
az redisenterprisecommands come from a CLI extension that installs on first use. - Knowledge of what the application stores: pure cache entries that can be rebuilt, or data that must not disappear, such as sessions, queues or locks.
Step 1: Confirm the memory state
Connect and read the memory, stats and keyspace sections:
# Azure Managed Redis
redis-cli -h contoso-cache.westeurope.redis.azure.net -p 10000 -a "<access-key>" --tls INFO memory
# Self-managed Redis
redis-cli -h redis01.contoso.com -p 6379 INFO memory
redis-cli -h redis01.contoso.com -p 6379 INFO stats
redis-cli -h redis01.contoso.com -p 6379 INFO keyspaceFor Azure Cache for Redis Basic, Standard and Premium you can also run commands in the portal's Console, unless the cache uses a virtual network, Private Link, or has access keys disabled.
The fields that matter:
| Section | Field | What it tells you |
|---|---|---|
| memory | used_memory | Bytes allocated by Redis |
| memory | maxmemory | The configured limit |
| memory | maxmemory_policy | The active eviction policy |
| memory | used_memory_rss | Memory as seen by the operating system |
| memory | mem_fragmentation_ratio | Ratio of used_memory_rss to used_memory, including other process overhead |
| memory | mem_not_counted_for_evict | Replica and AOF buffers, not counted for eviction |
| memory | used_memory_dataset | Bytes used by the data itself |
| stats | evicted_keys | Keys evicted because of maxmemory |
| stats | expired_keys | Keys removed because their TTL ran out |
| stats | current_eviction_exceeded_time | Milliseconds since used_memory last rose above maxmemory |
| keyspace | dbN:keys=...,expires=... | Total keys and how many have a TTL |
INFO errorstats also counts errors by prefix, so a growing errorstat_OOM count confirms how often clients hit the limit.
Step 2: Work out why eviction isn't happening
Compare three things:
- Policy is
noeviction. Eviction is disabled by design. Either change the policy or treat the instance as a store and add memory. - Policy is
volatile-*andexpiresis much lower thankeys. Most keys have no TTL, so there's little or nothing to evict. Ifexpires=0, the cache behaves exactly likenoeviction. evicted_keysis rising but the error still appears. Eviction is working but can't keep up, or a single command adds a large amount of data at once. Redis documentation notes that a command that adds a lot of data, such as storing a big set intersection, can temporarily exceed the limit by a large amount. Look at big keys and write bursts.
Step 3: Choose the right eviction policy
Redis's own guidance, applied to common situations:
| Workload | Recommended policy | Why |
|---|---|---|
| Pure cache, a subset of keys is hot | allkeys-lru | Good default when you have no reason to prefer another |
| Pure cache, access frequency matters more than recency | allkeys-lfu | Keeps keys that are used often |
| Pure cache, all keys accessed about equally | allkeys-random | Cheap and fair |
| You can predict which keys are good candidates and give them short TTLs | volatile-ttl | Evicts what is about to expire anyway |
| Same instance holds cache keys and keys that must persist | volatile-lru or volatile-lfu | Only TTL keys are evicted; every cache key needs a TTL |
| Data must never be evicted (queues, locks, primary data) | noeviction | Writes fail instead of silently losing data; size the instance accordingly |
Redis recommends separate instances rather than mixing cache and persistent keys where possible. allkeys-lru is also slightly more memory-efficient than relying on TTLs, because an expiration costs memory per key.
For a semantic cache in front of an LLM, such as the one described in production LLMOps and enterprise RAG architecture, entries can always be regenerated, so allkeys-lru or allkeys-lfu with TTLs is usually the right fit.
Step 4: Change the policy
Self-managed Redis
Change it at runtime, then persist it:
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG REWRITECONFIG REWRITE writes the running configuration back to the redis.conf the server was started with. Alternatively, edit redis.conf directly:
maxmemory 4gb
maxmemory-policy allkeys-lruIf the server has replicas or AOF persistence, set maxmemory below the physical RAM so the replication and AOF buffers (reported as mem_not_counted_for_evict) have room. Redis doesn't count those buffers against maxmemory, to avoid an eviction feedback loop.
Azure Cache for Redis
The CONFIG command is disabled; calling it returns an unknown command error. In the portal, open the cache, select Advanced settings, and change Maxmemory policy. With the Azure CLI:
az redis update \
--name contoso-cache \
--resource-group rg-cache-prod \
--set "redisConfiguration.maxmemory-policy"="allkeys-lru"Azure Managed Redis
The policy is a database property. Accepted values are AllKeysLFU, AllKeysLRU, AllKeysRandom, NoEviction, VolatileLFU, VolatileLRU, VolatileRandom and VolatileTTL:
az redisenterprise database update \
--cluster-name contoso-cache \
--resource-group rg-cache-prod \
--eviction-policy AllKeysLRUStep 5: Give cache keys an expiration
Even with an allkeys-* policy, TTLs keep memory under control proactively, and Microsoft notes that eviction under memory pressure adds server load. Set the TTL when you write:
redis-cli SET product:1001 '{"name":"Widget"}' EX 3600
redis-cli EXPIRE session:abc123 1800
redis-cli TTL product:1001TTL returns the remaining seconds. Make TTLs part of the cache wrapper in your application rather than relying on each developer to remember them.
Step 6: Find and fix big keys
A few very large keys can consume most of the memory, defeat eviction and slow replication. Scan for them:
redis-cli --bigkeys
redis-cli --memkeys
redis-cli MEMORY USAGE product:catalog:all--bigkeys and --memkeys scan the whole keyspace and report the biggest keys and average sizes per type; you can add -i 0.1 to sleep between batches on a busy server. MEMORY USAGE returns the bytes a single key consumes, including overhead.
Azure Managed Redis also exposes preview shard-level metrics that count large collections and strings per shard. Microsoft recommends keeping individual values under 512 KB for best performance; split large values across multiple keys, compress serialized values, and trim collections that grow without bound. On Flash Optimized tiers, large keys stay in RAM rather than moving to flash, which can cause OOM errors even when flash space is available.
Step 7: Leave headroom for fragmentation and replication
Azure Cache for Redis
Basic, Standard and Premium caches reserve memory with two settings under Advanced settings:
maxmemory-reserved: memory per instance in a cluster for non-cache operations such as replication during failover.maxfragmentationmemory-reserved: memory reserved to absorb fragmentation.
Each defaults to about 10% of maxmemory, and both can be set between 10% and 60%. Raise them for write-heavy workloads or if you store values of 100 KB or more. Be careful on a full cache: raising the reservation lowers the memory available for data, and the cache evicts until both used_memory and used_memory_rss are below the new limit. Scaling via CLI, PowerShell or REST ignores reservation values in the same request; set them after the scale operation completes.
Azure Managed Redis
There are no reservation settings to tune. Watch Used Memory Percentage rather than Used Memory: with high availability enabled, Used Memory includes the replica and can look roughly twice the dataset size, while the percentage already accounts for the SKU limit. Microsoft suggests scaling to a larger size if Used Memory Percentage stays above 75%. Neither metric includes fragmentation.
Step 8: Monitor and alert
Create Azure Monitor alerts on:
- Used Memory Percentage, so you can scale before the limit is reached.
- Evicted Keys, to see when eviction starts and whether it is constant.
- Cache Misses, because a jump after a policy change can mean the wrong keys are being evicted.
On Azure Managed Redis, rate-based metrics such as Evicted Keys now default to the Average aggregation; update older alerts that used Total. On self-managed Redis, collect used_memory, maxmemory, evicted_keys and the hit ratio, calculated as keyspace_hits / (keyspace_hits + keyspace_misses).
Verification
INFO memoryshows the intendedmaxmemory_policy.INFO keyspaceshowsexpiresclose tokeysfor cache databases using a volatile policy.- Under load,
evicted_keysrises whileerrorstat_OOMstays flat. - Application logs no longer show the OOM error, and the cache hit ratio is acceptable.
- For queues, locks or other data that must persist, the instance is sized so that
noevictionnever triggers.
Troubleshooting
OOM command not allowed when used memory > 'maxmemory'. right after deploying a new Azure cache. The application writes keys without TTLs and the default volatile-lru has nothing to evict. Add TTLs or switch to allkeys-lru.
ERR unknown command 'CONFIG' on Azure Cache for Redis. CONFIG is blocked on the managed service, including through StackExchange.Redis IServer.ConfigSet. Use the portal or az redis update.
Errors continue after switching to an allkeys-* policy. Check for a few huge keys with --memkeys, and for commands that add large amounts of data in one operation. A single oversized write can exceed the limit before eviction catches up.
used_memory is below the limit but Azure Cache for Redis still evicts. used_memory_rss counts too. High fragmentation pushes RSS over the limit; raise maxfragmentationmemory-reserved and reduce large values.
Memory fills on only some shards. On clustered caches, hash tags or big keys can concentrate data on one shard. On Azure Managed Redis, split Shard Memory Used by Slots (Range) to find the imbalance.
Data you needed was evicted. You used an allkeys-* policy on an instance that also stores non-cache data. Move that data to a separate instance with noeviction, or switch to a volatile policy and give only cache keys TTLs.
Checklist
- Root cause identified from
maxmemory_policy,keysversusexpires, andevicted_keys. - Eviction policy matches the workload; cache and persistent data separated where possible.
- TTLs set by the cache layer for every rebuildable key.
- Big keys found and split or compressed.
- Headroom left for replication buffers and fragmentation.
- Alerts on Used Memory Percentage and Evicted Keys, with a scaling plan.
References
- https://redis.io/docs/latest/develop/reference/eviction/
- https://redis.io/docs/latest/commands/info/
- https://redis.io/docs/latest/commands/set/
- https://redis.io/docs/latest/commands/memory-usage/
- https://redis.io/docs/latest/commands/config-rewrite/
- https://redis.io/docs/latest/develop/tools/cli/
- https://github.com/redis/redis/blob/7.4.0/redis.conf
- https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-best-practices-memory-management
- https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-configure
- https://learn.microsoft.com/en-us/azure/redis/best-practices-memory-management
- https://learn.microsoft.com/en-us/azure/redis/monitor-cache-reference
- https://learn.microsoft.com/en-us/azure/redis/how-to-redis-cli-tool
- https://learn.microsoft.com/en-us/cli/azure/redis
- https://learn.microsoft.com/en-us/cli/azure/redisenterprise/database