Choose the Right Redis maxmemory-policy for Django
Pick Redis maxmemory and maxmemory-policy settings for Django workloads: allkeys-lru or allkeys-lfu for caches, noeviction for Celery brokers and locks, volatile policies for mixed use, and how to split instances so evictions never drop queued tasks or sessions.
Problem statement
Redis keeps everything in memory. When it reaches maxmemory, the maxmemory-policy decides what happens: evict keys, or refuse writes. The wrong choice hurts Django in opposite ways. A cache with noeviction starts failing writes with OOM command not allowed, while a Celery broker with allkeys-lru silently deletes queued tasks. Many projects run cache, sessions, and Celery on one Redis with the default settings and discover the problem in production.
- Always set
maxmemoryexplicitly (leave headroom below the server or container limit). - Pure Django cache:
maxmemory-policy allkeys-lru(orallkeys-lfufor skewed access). - Celery broker, Celery results you rely on, locks, rate limiters with no TTL:
noeviction. - Sessions in Redis:
volatile-lruwith session TTLs, or better, a separate instance withnoevictionand enough memory. - If roles share one instance, split them; one policy cannot be right for all of them.
Step-by-step solution
1. Inventory what lives in Redis
redis-cli INFO keyspace
redis-cli --scan --pattern '*' | head -50
redis-cli MEMORY USAGE some:key
Typical Django keys: cache entries (:1:views.decorators...), sessions (django.contrib.sessions.cache...), Celery queues (celery, _kombu.binding.*), Celery results (celery-task-meta-*), Channels groups, and rate-limit counters. Note which ones must never disappear.
2. Configure a cache instance
# redis-cache.conf
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 10
save ""
appendonly no
allkeys-lru evicts the least recently used keys among all keys, which is exactly what a cache should do. allkeys-lfu evicts the least frequently used, which keeps popular items better when access is very skewed. Without persistence, restarts are instant and the cache simply refills.
3. Configure a broker instance
# redis-broker.conf
maxmemory 1gb
maxmemory-policy noeviction
appendonly yes
appendfsync everysec
With noeviction, when memory is full Redis rejects writes with OOM command not allowed, so .delay() fails loudly instead of tasks vanishing. Alert at 70 to 80 percent memory, and keep queues short by scaling workers. Set CELERY_RESULT_EXPIRES so results do not fill the broker.
4. Handle sessions and mixed instances
With volatile-* policies, only keys with a TTL can be evicted. Django's cache-based sessions have TTLs, so volatile-lru would evict sessions (logging users out) before refusing writes. If you must share one instance for cache and Celery, volatile-lru protects Celery queues (which have no TTL) while letting cache entries go, but cache entries set with timeout=None become unevictable. A dedicated cache instance is simpler and safer.
5. Monitor evictions and memory
redis-cli INFO stats | grep -E "evicted_keys|keyspace_hits|keyspace_misses"
redis-cli INFO memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
Rising evicted_keys on a cache instance means the cache is too small for its working set; hit ratio tells you whether that matters. Any eviction on a broker instance is a configuration error.
Explanation
When used_memory exceeds maxmemory, Redis runs the configured policy on each write. Eviction policies sample keys and remove those that best match the criterion (least recently used, least frequently used, or nearest expiry), among all keys or only keys with a TTL. noeviction refuses commands that would increase memory. Django's cache is designed to tolerate missing keys; Celery's broker and locks are not. Matching policy to data durability is the whole decision.
Edge cases / notes
- Container limits. Set
maxmemorybelow the container memory limit, leaving room for fragmentation, replication buffers, and fork during persistence. - Managed services. ElastiCache, Memorystore, and Azure set policies through parameter groups; defaults vary by provider.
- Big values. A few large cached values can push out many small useful ones; cap what you cache.
Next steps
- If writes already fail, see Fix Redis OOM Command Not Allowed in Django.
- Set persistence per role with Configure Redis Persistence for Django and Celery.
- Review settings with the Django Redis Production Checklist.
FAQ
What is the default maxmemory-policy?
noeviction. It is safe for brokers but makes a dedicated cache fail writes when full.
Which policy should a Django cache use?
allkeys-lru in most cases, or allkeys-lfu when a few keys are much hotter than the rest.
Can eviction delete Celery tasks?
Yes, with allkeys-* policies. Use noeviction on the broker instance.
Why are users logged out when Redis is full?
Cache-based sessions have TTLs and are evicted under volatile-* or allkeys-* policies. Give sessions their own instance or use cached_db sessions.