Redis Persistence

RDB snapshots vs AOF logs, the durability/performance trade-off, and how to configure each.

The introduction page mentioned that Redis is volatile by default — a restart with no persistence configured loses everything in memory. This page covers the two mechanisms Redis offers to change that, how they differ, and how to actually configure each.

RDB: point-in-time snapshots

RDB (Redis Database) persistence writes the entire in-memory dataset to a single compact binary file at a point in time. It's configured with save rules in redis.conf, each one meaning "trigger a snapshot if at least N seconds have passed AND at least M keys changed":

Plaintext
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir /var/lib/redis

This configuration snapshots after 900 seconds if at least 1 key changed, after 300 seconds if at least 10 keys changed, or after 60 seconds if at least 10,000 keys changed — multiple rules coexist so a quiet server still gets occasional snapshots while a very busy one snapshots more often. A snapshot can also be triggered manually:

Bash
redis-cli BGSAVE

BGSAVE forks a child process to write the snapshot, relying on the operating system's copy-on-write behavior so the main Redis process keeps serving reads and writes without blocking during the write — the fork itself is nearly instant, but a very high write rate during the snapshot can still cause real memory overhead, since every page a write touches during the fork has to be duplicated rather than shared. (The older SAVE command does the same snapshot synchronously, blocking the server for its entire duration — essentially never the right choice on a live server.)

The trade-off: RDB restores extremely fast (loading one binary file is much quicker than replaying a long log of individual writes), and it produces a single, easy-to-copy-elsewhere file — but any writes since the last snapshot are permanently lost if Redis crashes or is killed before the next one runs. With the save 60 10000 rule above, a crash could lose up to a minute's worth of writes (or fewer than 10,000 keys' worth of changes) that never made it into a snapshot.

AOF: an append-only write log

AOF (Append Only File) persistence takes a different approach: instead of periodic snapshots, it logs every write command as it happens, and reconstructs the dataset on startup by replaying that log from the beginning.

Plaintext
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

appendfsync controls how often the log is actually flushed to disk (as opposed to just handed to the operating system's write buffer), and it's the single most important trade-off in AOF configuration:

appendfsync value Behavior Durability Performance
always fsync after every single write Safest — at most one command lost on a crash Slowest — every write pays a disk fsync
everysec (default) fsync once per second Loses at most ~1 second of writes Good balance, the recommended default
no Let the OS decide when to flush Loses whatever the OS hadn't flushed yet Fastest, least durable

everysec is the right default for the overwhelming majority of use cases — it bounds data loss to roughly a second's worth of writes while avoiding the cost of an fsync on every single command.

AOF rewriting

Because AOF logs every write command ever made, it grows without bound over the life of a busy server — including redundant history like a counter that was incremented a million times, even though only its final value matters for reconstructing state. BGREWRITEAOF compacts the log by rewriting it as the minimal set of commands needed to recreate the current dataset from scratch, the same copy-on-write forking trick BGSAVE uses to avoid blocking the main process:

Bash
redis-cli BGREWRITEAOF

Redis can also trigger this automatically based on how much the file has grown since the last rewrite (auto-aof-rewrite-percentage, auto-aof-rewrite-min-size), which is the normal way this happens in practice rather than a manual, remembered step.

Combining both

Since Redis 4.0, aof-use-rdb-preamble yes (the default) makes AOF rewrites store an RDB-formatted snapshot as the start of the rewritten AOF file, followed by any commands logged since — giving RDB's fast restart time together with AOF's tighter durability window, in one file.

Choosing a persistence strategy

RDB only AOF only Both (recommended for durability-sensitive use) Neither
Data loss window on crash Minutes (last snapshot interval) ~1 second with everysec ~1 second, with RDB-speed restarts Everything since last restart
Restart speed Fast Slower (or fast, with the RDB preamble) Fast N/A
Disk write overhead Low (periodic only) Continuous Continuous None
Good fit for A pure, fully-rebuildable cache Any data Redis is the source of truth for Data that must survive a crash with minimal loss A cache where losing everything on restart is genuinely fine

A Redis instance used purely as a cache-aside layer in front of a real database (as on the caching-patterns page) can often run with persistence disabled entirely — every key is trivially rebuildable from the source of truth on a miss, so losing the whole cache on restart just means a temporary wave of cache misses, not lost data.

Common mistakes

  • Assuming RDB alone means "durable" — a crash between snapshots loses every write since the last one, which can be minutes of data depending on the configured save rules.
  • Setting appendfsync always on a high-throughput application without measuring the cost — it's the safest setting, but it puts a disk fsync on the critical path of every single write.
  • Never enabling (or triggering) AOF rewriting, letting the file grow to many times the size of the actual dataset it represents.
  • Forgetting that BGSAVE/BGREWRITEAOF's fork needs real free memory headroom — under a high write rate during the fork, copy-on-write can transiently use significantly more memory than the dataset's steady-state size, which matters when sizing a Redis instance close to its memory limit.