Redis persistence (RDB and AOF) and eviction policies
Persistence decides what a restart brings back; the eviction policy decides what a full Redis deletes, and each instance has exactly one.
Predict first
Before you read: predict
ExamHall's question cache and its BullMQ grading queue share one Redis with a maxmemory cap. After grading jobs went missing, the team switched its policy from allkeys-lru to volatile-lru, since BullMQ's keys carry no TTL. The question cache writes its entries with plain SET, also with no TTL. At the 09:00 exam start, 200 grading jobs are waiting and the cache writes about 30 times what the free memory holds.
What happens?
The 30-second version
Redis keeps everything in RAM. A crash loses every write since the last RDB snapshot; an AOF loses at most about a second. At maxmemory the policy decides: noeviction refuses what may add data, allkeys-* evicts any key, volatile-* evicts only keys with a TTL and otherwise refuses. One instance has one policy, so keep queues apart from caches.
Persistence decides what a restart brings back; the eviction policy decides what a full Redis deletes, and each instance has exactly one.
How it works
Step 1 of 13
Analogy: A police station's evidence store
Every exhibit sits on the store's shelves, and nothing is kept anywhere else.
| At the evidence store | In Redis |
|---|---|
| the quarterly audit photographs every shelf; after a fire the photographs show the store as it was then | an RDB snapshot and what a crash loses (steps 2–3) |
| the officer closing up properly photographs the shelves first; a fire takes no photograph | a clean stop saves, SIGKILL does not (step 4) |
| the custody book records each exhibit in and out as it happens, and replaying it rebuilds the store | the AOF (step 5) |
| the shelves are full | maxmemory (step 7) |
| the hatch refuses anything that might need more shelf space | noeviction (step 8) |
| a clear-out destroys whatever has sat untouched longest | allkeys-lru (step 9) |
| a clear-out may destroy only exhibits already given a disposal date; with none dated, the hatch can only refuse | volatile-* (step 10) |
| counterfeit goods awaiting routine destruction share the shelves with evidence for open cases, under one clear-out rule | one instance, one policy (step 11) |
In real terms: for each Redis you run, write down what a restart must bring back and what may be deleted when it is full; if two kinds of data give different answers, they need two instances.
Breaks down when: destroying an exhibit takes a signed form; Redis evicts a key silently, and only a counter moves.
Contrasting case: a pure cache that can be refilled from Postgres needs neither persistence nor noeviction: losing any key costs one miss.
Examples, run for real
4.1 ExamHall: the queue that shared the cache's policy
EXH-5020: at ExamHall's 09:00 exam start the question cache and the BullMQ grading queue shared one Redis running allkeys-lru. The cache's writes filled memory, and Redis evicted the grading jobs' keys to make room. MR !5320 gives the queue its own Redis with noeviction and leaves the cache on allkeys-lru.
4.1 EXH-5020 one Redis, allkeys-lru: 200 grading jobs, then 60000 question-cache writes · cache writes refused 0 · grading jobs kept 0 of 200
4.1 MR !5320 queue Redis (noeviction) + cache Redis (allkeys-lru): the same writes · cache writes refused 0 · grading jobs kept 200 of 200
4.1 MR !5320 20000 more jobs into the full queue Redis · added until it was full · refused with an OOM error the rest · other errors 0 · the first 200 jobs kept 200 of 200
Every grading job was gone and no write was refused, so nothing reported an error. After the split, the jobs survive the same writes, and a producer that overfills the queue's Redis gets an OOM error instead (steps 11–12).
4.2 Payments ledger: no cap in a 64 MB container
A ledger's FX-rate cache runs in a container limited to 64 MB, first with no maxmemory, then with maxmemory 40mb and allkeys-lru.
4.2 payments ledger FX cache in a 64 MB container, no maxmemory (0, the default): 200000 writes · kernel OOM kills 1 · new redis-server process yes · keys afterwards none
4.2 payments ledger FX cache in a 64 MB container, maxmemory 40mb, allkeys-lru: 200000 writes · kernel OOM kills 0 · new redis-server process no · keys afterwards some
With no cap, the kernel killed Redis and the restarted process came back empty; with a cap below the container's limit, Redis evicted keys and kept running (steps 7, 13).
Picture it

Try it
Answer first, then check. Nothing is saved.
Question 1 of 6
A payments API keeps two kinds of keys in one Redis with a maxmemory cap: FX-rate cache entries (plain SET, no TTL, fetched again on a miss) and 500 idempotency keys (SET … EX 86400), which must outlive any retry or a retried charge runs twice. The platform team runs every shared Redis on volatile-lru and will not add an instance. At month-end the FX job writes about 30 times what the free memory holds.
Which way of writing the two kinds keeps every idempotency key while every FX-rate write still succeeds?
Question 2 of 6
A ledger caches posting confirmations on two Redis servers. X runs save 900 1 and appendonly no, and its last snapshot ran right after posting 300. Y runs appendonly yes, appendfsync everysec and save "". Both receive the same 500 postings, the last 200 within a minute. After the last one is acknowledged, the Redis process on each machine is killed with kill -9, a process kill, not a power cut: the machines stay up and Redis restarts at once.
How many postings does each server load?
Question 3 of 6
A payments ledger's job queue has its own Redis with noeviction, and a backlog has filled it past maxmemory. The API then sends, in this order: GET a posting's status, APPEND a line to an existing audit string, EXPIRE an existing idempotency key in one hour, LPOP the next job ID from an existing list.
Which commands succeed?
Question 4 of 6
A ledger's FX-rate cache runs Redis in a container limited to 64 MB (--memory 64m, no swap), with maxmemory 200mb, allkeys-lru and no persistence (save "", no AOF). At month-end the FX job writes 150,000 rates of 512 bytes each, about 75 MB of values.
What happens?
Question 5 of 6
A chat service holds presence sessions in a Redis started from the redis:7-alpine image with no config file. After the 120th session an operator runs BGSAVE, which finishes; 80 more sessions follow. A few seconds after the last write, the Redis process is restarted: once after a clean stop (SIGTERM, which docker stop sends first), once after a crash (kill -9).
How many sessions does each restart bring back?
Question 6 of 6
A video service keeps viewer sessions (SET … EX 86400) on a Redis of their own, with AOF on and a maxmemory cap. Viewers who have signed in read their session on every request. The goal: no viewer who has signed in is ever logged out by memory pressure; refusing a new sign-in while memory is full is acceptable.
Which maxmemory-policy meets the goal?
Go deeper
Pro tips
- Kill it before you trust it. In staging, write a known number of keys,
kill -9the Redis process, let it restart, and count what came back. When: before putting sessions, idempotency keys or a queue on a Redis (steps 2–5). Verify: each sends SIGKILL to the Redis process and counts the keys the restarted process loaded. - Set
maxmemorybelow the container's memory limit. The Redis docs advise leaving "a little RAM free to store the buffers" when persistence or replication is on. When: any Redis in a container or VM with a hard memory limit (steps 7, 13).
Source
- Redis docs, Redis persistence (source
content/operate/oss_and_stack/management/persistence.md, redis/docs branch main): https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/ · fetched 2026-10-18. "RDB persistence performs point-in-time snapshots of your dataset at specified intervals"; "in case of Redis stopping working without a correct shutdown for any reason you should be prepared to lose the latest minutes of data"; "If your computer running Redis stops, your power line fails, or you accidentally kill -9 your instance, the latest data written to Redis will be lost"; "When you restart Redis it will re-play the AOF to rebuild the state"; "you may lose 1 second of data if there is a disaster"; "The suggested (and default) policy is to fsync every second" (steps 1–5). Valid as of 2026-10-18. - Redis docs, Key eviction (source
content/develop/reference/eviction/index.md, redis/docs branch main): https://redis.io/docs/latest/develop/reference/eviction/ · fetched 2026-10-18. "Set maxmemory to zero to specify that you don't want to limit the memory for the dataset. This is the default behavior for 64-bit systems"; "Keys are not evicted but the server will return an error when you try to execute commands that cache new data"; "Note that commands that only read existing data still work as normal"; "The volatile-xxx policies behave like noeviction if no keys have an associated expiration"; "you should consider running two separate Redis instances in a case like this, if possible"; "we recommend that you set maxmemory to leave a little RAM free to store the buffers" (steps 7–11, tip 2). Valid as of 2026-10-18. - BullMQ docs, Going to production, Max memory policy (source
docs/gitbook/guide/going-to-production.md, taskforcesh/bullmq branch master): https://docs.bullmq.io/guide/going-to-production · fetched 2026-10-18. "BullMQ on the other hand cannot work properly if Redis evicts keys arbitrarily"; "This is the only setting that guarantees the correct behavior of the queues" (step 12). Valid as of 2026-10-18.
Related lessons
Checked against the tools and docs as of 2026-10-18.