Skip to main content
Redis · lesson 7 of 14
Redis intermediate Lesson 7 of 14

RDB vs AOF: What Survives a Hard Kill and What Doesn't

A graceful restart saves your data by default — Redis snapshots on SIGTERM. A hard kill (docker kill, a power loss, an OOM kill) gives it no such chance, and only AOF protects against that. Then: the new BACKUP command family.

By SkillByExample · Published

redis persistence rdb aof backup durability

The same container, the same key, two different shutdowns — and only one of them loses data.

The bug: a hard kill loses recent writes

docker exec redis-lesson redis-cli SET durable "will it survive"
docker restart redis-lesson
# ... container comes back up ...
docker exec redis-lesson redis-cli GET durable
OK
will it survive

That survived — docker restart sends SIGTERM, and Redis performs an RDB save on a graceful shutdown by default, independent of whatever periodic save points are configured. Now compare a hard kill:

docker exec redis-lesson redis-cli SET fragile "will this survive a hard kill"
docker kill redis-lesson
docker start redis-lesson
docker exec redis-lesson redis-cli GET fragile
OK

Nothing came back — fragile is gone. docker kill sends SIGKILL, which gives Redis no chance to run any shutdown code at all. No RDB save happens, so anything written since the last snapshot — scheduled or shutdown-triggered — is simply lost. This is the real gap in RDB-only persistence: not “Redis loses data on restart,” but specifically “Redis loses recent data on a hard crash.”

The fix: AOF, enabled from container start

docker rm -f redis-lesson
docker run -d --name redis-lesson -p 6379:6379 redis:8-alpine --appendonly yes
docker exec redis-lesson redis-cli CONFIG GET appendonly
appendonly
yes

--appendonly yes on the redis-server command line turns on the append-only file from the moment the server starts — turning it on later with CONFIG SET appendonly yes at runtime works too, but doesn’t survive a restart unless the config is also persisted, so starting with it enabled is the more reliable habit for a container that might get recreated.

docker exec redis-lesson redis-cli SET protected "aof should save this"
docker kill redis-lesson
docker start redis-lesson
docker exec redis-lesson redis-cli GET protected
OK
aof should save this

Same hard kill, different outcome — protected survives, because every write was already logged to the append-only file before the kill happened, not waiting on a snapshot.

The new BACKUP command family (Redis 8.10+)

docker exec redis-lesson redis-cli BACKUP START
docker exec redis-lesson redis-cli BACKUP LIST
OK
/data/backupdir/appendonly.aof.2.base.rdb

BACKUP START opens a backup window and produces a BASE snapshot immediately; BACKUP LIST shows the files pinned so far — you can start copying the BASE file while Redis keeps accumulating new writes into its INCR file underneath.

docker exec redis-lesson redis-cli BACKUP SEAL
docker exec redis-lesson redis-cli BACKUP LIST
OK
/data/backupdir/appendonly.aof.2.base.rdb
/data/backupdir/appendonly.aof.2.incr.aof
/data/backupdir/appendonly.aof.manifest

BACKUP SEAL freezes the backup — the INCR file (everything written since START) and a manifest tying all three files together now appear. Restoring loads BASE + INCR, so the restored data reflects the state at the seal boundary, not just the earlier snapshot.

docker exec redis-lesson redis-cli BACKUP CLEANUP
docker exec redis-lesson redis-cli BACKUP STATUS
OK
state
idle
error

start_time
0
end_time
0

BACKUP CLEANUP releases the pinned files once they’ve been copied somewhere durable, and BACKUP STATUS confirms the backup process is back to idle — ready to start the next one.

Practice

1. Check BACKUP STATUS mid-backup, before sealing it.
docker exec redis-lesson redis-cli BACKUP START
docker exec redis-lesson redis-cli BACKUP STATUS
OK
state
incrementing
error

start_time
1789313506
end_time
0

state: incrementing means the BASE snapshot is done and Redis is now accumulating writes into the INCR file — end_time: 0 confirms it hasn’t been sealed yet.

2. Check the append-only fsync policy currently configured.
docker exec redis-lesson redis-cli CONFIG GET appendfsync
appendfsync
everysec

everysec is the default — fsync once per second, which is fast and still bounds any hard-kill data loss to roughly the last second of writes, rather than everything since the last RDB snapshot.

3. Abort an in-progress backup instead of sealing it.
docker exec redis-lesson redis-cli BACKUP ABORT
docker exec redis-lesson redis-cli BACKUP STATUS
OK
state
failed
error
aborted by user
start_time
1789313506
end_time
0

BACKUP ABORT only works before SEAL. The status afterward reports state: failed with the reason (aborted by user) rather than quietly resetting to idle — the failed state is a real, inspectable record of what happened to that backup attempt, not just a silent reset.

Next: replication — leader-follower, WAIT, and read-only replicas.

Frequently Asked Questions

Why did data survive a graceful docker restart with no special configuration?
Redis's default save points (every 3600s/300s/60s depending on how many keys changed) almost certainly hadn't fired in the few seconds between the SET and the restart — what actually saved it is that Redis performs an RDB save on a clean shutdown by default, triggered by the SIGTERM a graceful docker restart sends. That's a separate mechanism from the periodic save points.
Why did the same key get lost after a hard kill (docker kill)?
docker kill sends SIGKILL, which terminates the process immediately with no opportunity to run any shutdown code — no RDB save happens, so anything written since the last snapshot (scheduled or shutdown-triggered) is gone. This is the actual failure mode RDB-only persistence has: anything between snapshots is at risk of a hard crash, not just a clean shutdown.
Does enabling AOF guarantee zero data loss?
No — it depends on the fsync policy. The default, appendfsync everysec, fsyncs once per second, so up to roughly one second of writes can still be lost in a hard kill that happens between fsyncs. appendfsync always fsyncs on every write for near-zero loss at a real performance cost; appendfsync no relies entirely on the OS's own flush timing and offers the weakest guarantee of the three.
What does the new BACKUP command family add that copying dump.rdb didn't already do?
It produces a coordinated, self-contained backup (a BASE snapshot, an INCR file of writes since, and a manifest describing both) without pausing writes or manually juggling AOF rewrite settings — and because starting and sealing are separate steps, a control plane can stagger BACKUP START across many cluster nodes so they don't all fork at once. Copying dump.rdb by hand only ever captured the RDB half of the picture and needed manual care around AOF rewrites happening concurrently.
Should a production Redis use RDB, AOF, or both?
Both, for most cases that care about durability: RDB gives fast, compact snapshots good for backups and quick restarts; AOF gives much tighter recovery-point granularity against a hard crash. Redis replays AOF on restart when both are enabled, since it's the more complete record — RDB alone accepts more potential data loss in exchange for simplicity and speed.