Redis Persistence, Eviction Policies and Safe Operations
System Design & ArchitectureLesson 4 of 46 min read
What you'll learn
- Compare RDB snapshots and the append-only file, including what each can lose
- Choose a maxmemory-policy that matches how the instance is used
- Lock down a Redis instance with network binding, authentication and ACLs
- Monitor memory, slow commands and big keys, and plan for failure with replication and tested restores
On this page
A clinic's patient portal stores login sessions in Redis. One morning the server running Redis is rebooted for patching, and every patient is logged out at once. Was that a bug? It depends entirely on whether anyone decided what should happen to the data on restart. Redis is a memory database first; persistence, memory limits and access control are all things you must configure on purpose.
Two ways Redis writes to disk
RDB takes point-in-time snapshots of the whole dataset into a compact file. Snapshots are triggered by save rules in the config (for example, after N changes within M seconds) or manually with BGSAVE, which forks a child process to write the file while the parent keeps serving. Restarts load the file quickly, and the file is a convenient backup unit. The cost: anything written since the last snapshot is lost on a crash.
AOF (append-only file) logs every write command. On restart Redis replays the log. The appendfsync setting controls how often the log is flushed to disk: always is safest and slowest, everysec (a common choice) risks about a second of writes, and no leaves the timing to the operating system. Redis rewrites the AOF in the background so it does not grow forever. Many deployments enable both, using the AOF to restore the freshest state and RDB files for backups.
| RDB snapshot | AOF | |
|---|---|---|
| What it stores | Full dataset at a moment in time | Log of write commands |
| Data you can lose in a crash | Everything since the last snapshot | Up to about a second with everysec; less with always |
| Restart speed | Fast | Slower, because the log is replayed |
| File size | Compact | Larger, shrunk by background rewrite |
| Good for | Backups, caches that can warm quickly | Data you cannot easily rebuild |
# Persistence: AOF every second plus periodic snapshots
appendonly yes
appendfsync everysec
save 900 1
save 300 10
# Memory: cap Redis and decide what happens when the cap is reached
maxmemory 256mb
maxmemory-policy volatile-lru
# Network: do not listen on the public internet
bind 127.0.0.1
protected-mode yesDefault save rules and defaults for several settings differ between Redis versions, so state them explicitly in your config rather than trusting memory. Two operational notes: BGSAVE replies Background saving started and works by forking, which briefly increases memory use through copy-on-write when many keys change during the snapshot, so leave headroom. And none of this replaces a backup that has been restored at least once on another machine; an untested backup is a hope.
When memory runs out: eviction
Without maxmemory, Redis grows until the operating system intervenes. With it, Redis applies the configured maxmemory-policy when a write would exceed the limit. The default is noeviction, which rejects writes with OOM command not allowed when used memory > 'maxmemory'. That is the right behaviour for primary data and a nasty surprise for a cache you assumed would evict.
| Policy | Evicts | Use when |
|---|---|---|
| noeviction | Nothing; writes fail | Redis holds data you cannot lose |
| allkeys-lru | Least recently used, any key | Pure cache; the common choice |
| allkeys-lfu | Least frequently used, any key | Cache with a stable hot set |
| volatile-lru / volatile-lfu | Same, but only keys that have a TTL | Mixed instance: cache keys with TTL, durable keys without |
| volatile-ttl | Keys with the shortest remaining TTL | Expiry order is meaningful |
| allkeys-random / volatile-random | Random keys | Rarely; uniform access patterns |
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
127.0.0.1:6379> CONFIG SET maxmemory-policy allkeys-lru
OK
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"The first reply shows noeviction only if the server still has the default policy; if your instance was configured differently you will see that value. CONFIG SET changes the running server only: write the same setting in redis.conf or it reverts on restart. For the cache-design reasoning behind LRU and LFU, see Caching: Strategies, Eviction and Pitfalls.
Locking the door
A Redis instance reachable from the internet with no password is a standard way to leak data and lose a server, because Redis was designed to run inside a trusted network. Treat these as minimum requirements: bind to private interfaces, firewall the port, keep protected-mode on, require authentication and give each application the least access it needs with ACLs. Add TLS if traffic crosses networks you do not control.
127.0.0.1:6379> ACL SETUSER portal on >CHANGE_ME_TO_A_LONG_RANDOM_SECRET ~session:* -@all +get +set +del +expire +ttl
OK
127.0.0.1:6379> ACL WHOAMI
"default"That user may only touch keys starting with session: and use five commands, so a bug or stolen credential in the portal cannot run FLUSHALL or read other applications' data. Store the real secret in your secrets manager, never in the repository. (ACL WHOAMI shows the user of the current connection; here it is still the default user until the client authenticates as portal.)
Watching a running instance
- Memory:
INFO memoryreportsused_memory_humanand, when set, the configured limit. Alert well before the limit, not at it. - Slow commands:
SLOWLOG GET 10lists the slowest recent commands, which usually reveals an accidentalKEYS, a hugeLRANGEorHGETALLon an enormous hash. - Big keys:
redis-cli --bigkeyssamples the keyspace and shows the largest key per type, andMEMORY USAGE keyreports one key's size. Large keys cause latency spikes and slow deletes (useUNLINKinstead ofDELto free them in the background). - Persistence health:
INFO persistenceshows whether AOF is on and the status of the last save. Alert when a save fails. - Hit rate:
INFO statsincludeskeyspace_hitsandkeyspace_misses; the ratio tells you whether a cache is earning its memory.
Common mistakes and the symptoms they cause
- Assuming Redis is durable by default. Symptom: sessions or queued jobs vanish after a restart. Decide on AOF/RDB per instance, and keep truly critical data in a database.
- Leaving the default `noeviction` on a cache. Symptom:
OOM command not allowed when used memory > 'maxmemory'errors in the application once the cache fills. Choose an eviction policy deliberately. - No `maxmemory` at all. Symptom: the host starts swapping or the kernel kills the Redis process, which looks like a random crash.
- Exposing Redis to the public network without authentication. Symptom: unexpected keys or configuration changes, and eventually a compromised host. Bind privately, authenticate and use ACLs.
- **Running
FLUSHALL,KEYS *orDEBUGon a shared instance.** Symptom: an outage caused by a well-meaning engineer. Restrict dangerous commands with ACLs. - Never testing a restore. Symptom: during a real incident the RDB file turns out to be old, empty or unreadable.
How this shows up in real projects and interviews
Interviewers ask "is Redis durable?" to see whether you can say "it depends on RDB/AOF settings, and even then it is not a system of record unless you accept the loss window". They also ask what you would do when Redis memory is full, which is a question about eviction policy and key lifetimes. On a real team, the day-to-day work is monitoring memory and slow commands, setting TTLs on new key families as a review checklist item, and rehearsing failover. Containerised deployments add their own concerns, such as persistent volumes, covered in the Docker and Kubernetes courses.
Try it yourself
Write a redis.conf for a session store that holds 200 MB of sessions with 30-minute TTLs. Choose persistence settings and an eviction policy, justify each in a comment, and add an ACL command creating an application user limited to session:* keys. Then write a one-paragraph restore drill.
Show a hint
Sessions are rebuildable (users can log in again), so think about how much loss is acceptable. Use a volatile-* policy only if every session key has a TTL, otherwise eviction cannot free memory and writes may fail.
Key takeaways
- RDB is compact periodic snapshots (loses writes since the last one); AOF logs every write (loses about a second with
everysec); many setups use both. - Set
maxmemoryand choose amaxmemory-policyon purpose:allkeys-lrufor a pure cache, avolatile-*policy for mixed use,noevictionfor data you cannot drop. - Never expose Redis publicly: bind privately, require authentication, use ACL users with minimal commands and key patterns.
- Monitor memory, slowlog, big keys and persistence status, use
SCAN/UNLINKrather thanKEYS/DELon big data, and restore-test your backups.
Test yourself
A trick from this lesson's ride: RDB is a photograph, AOF is a diary: a crash costs what happened after the last entry. Four more tricks like it wait along the route, each followed by a question.
Frequently asked questions
Is Redis persistent? What is the difference between RDB and AOF?
Redis can persist data in two ways. RDB writes periodic snapshots of the dataset, so you can lose writes since the last snapshot. AOF logs every write command and can be flushed every second or on every write, so it loses less. Either way, Redis is usually treated as a fast store, not the only copy of critical data.
What happens when Redis runs out of memory?
If maxmemory is set, Redis applies the maxmemory-policy. With noeviction (the default) write commands fail with an OOM error; with policies such as allkeys-lru it evicts keys to make room. Without a maxmemory limit, Redis keeps growing until the operating system runs out of memory.
How do I secure a Redis server?
Run it inside a private network, bind it to specific interfaces, keep protected mode on, firewall the port and require authentication. Use ACL users restricted to the commands and key patterns each application needs, add TLS across untrusted networks, and keep secrets out of source control.