Databases

RDB, AOF, Both, or Neither: Redis Persistence on a Small Server

Decide whether a small Redis needs RDB snapshots, an append-only file, both, or no persistence, check that saves are really happening, and prove a restore with a throwaway instance.

6 min readUpdated Tuesday, Oct 13, 2026
redisbackupconfigurationtroubleshooting

White bubbles frozen in clear blue lake ice, with snowy peaks and a golden sunset beyond

Redis keeps everything in memory. Persistence decides how much of it is still there after a restart, a crash, or the hosting provider’s “brief maintenance window.” Asking which option is best gets you nowhere. Ask how much you can afford to lose.

This note covers what each mode protects, how to switch modes without wiping your data on the way, how to check that saves are really happening, and how to prove a copy restores. Examples come from Redis 8.x; everything except the last BACKUP mention also applies to Redis 7.

What each mode protects

RDB takes a snapshot of the whole dataset every so often, and a restart loads the latest one. Here’s the built-in default schedule:

save 3600 1 300 100 60 10000

Read it in pairs: seconds, then changes. Take a snapshot after an hour if there was at least one write, after five minutes if there were 100, and after a minute if there were 10,000. A quiet server can go an hour between snapshots, so a crash loses everything written since the last one.

AOF (append-only file) logs every write and replays the log on startup. How much you lose depends on appendfsync:

  • everysec, the default: Redis forces the file to disk once a second, so a crash costs about a second of writes.
  • always: forces it to disk after every batch of writes. The Redis docs call this “very very slow, very safe.”
  • no: leaves flushing to the operating system. Linux normally flushes every 30 seconds or so.

Both is what the Redis docs recommend if you want safety close to a traditional database. On restart Redis loads the AOF, because it’s the more complete record, and you still get compact RDB files for backups. The docs actively discourage running AOF without RDB.

Neither suits a pure cache that the app can rebuild. Set save "" and appendonly no, and a restart means an empty, cold cache and nothing worse.

Rough mapping for a small server:

Redis holds You can lose Use
Cache entries only All of it Neither (or RDB, if a warm restart is worth it)
Sessions, rate-limit counters A few minutes RDB
A job queue, anything not stored elsewhere About a second AOF and RDB

What’s on disk

Look in Redis’s dir, which is /var/lib/redis on Debian’s packages. With both modes on, you’ll see something like this:

dump.rdb
appendonlydir/
    appendonly.aof.1.base.rdb
    appendonly.aof.1.incr.aof
    appendonly.aof.manifest

Since Redis 7.0, the AOF is a directory rather than one file. It holds a base (a snapshot from the last rewrite), one or more incremental files with writes since then, and a manifest that ties them together. Redis rewrites the AOF in the background as it grows. Each rewrite produces a new base, and the files are swapped in by replacing the manifest atomically.

That has two consequences. Back up the whole directory, not one file. And a copy taken in the middle of a rewrite can be invalid. The docs’ approach is to pause automatic rewrites while you copy:

redis-cli CONFIG GET auto-aof-rewrite-percentage   # note the value (default 100)
redis-cli CONFIG SET auto-aof-rewrite-percentage 0
redis-cli INFO persistence | grep aof_rewrite_in_progress   # wait for 0
# copy the appendonlydir directory
redis-cli CONFIG SET auto-aof-rewrite-percentage 100

dump.rdb is simpler. Redis writes each new snapshot to a temporary file and renames it into place when it’s complete, so copying dump.rdb is safe at any time. Redis 8.10 added a BACKUP command family that handles the AOF coordination for you. Check redis-server --version before you plan around it, since Debian 13 ships Redis 8.0.

Turning on AOF without losing everything

This one deserves its own heading. Suppose a server has been running RDB only, you set appendonly yes in redis.conf, and you restart. Redis looks for an AOF, finds none, and starts with an empty dataset. It ignores dump.rdb, even though the file is right there. Then the next clean shutdown snapshots that empty dataset over your old dump.rdb.

The safe sequence turns AOF on while the server is running, so Redis writes the first AOF from the data in memory:

sudo cp /var/lib/redis/dump.rdb /root/dump.rdb.before-aof
redis-cli CONFIG SET appendonly yes
redis-cli INFO persistence | grep -E '^(aof_enabled|aof_rewrite_in_progress|aof_rewrite_scheduled|aof_last_bgrewrite_status):'
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_bgrewrite_status:ok

Once both rewrite flags read 0 and the status reads ok, make the change permanent with redis-cli CONFIG REWRITE or by editing redis.conf by hand. Skip that step and the next restart quietly goes back to RDB only. After any later restart, compare DBSIZE with what it was before.

Is it actually saving?

redis-cli INFO persistence | grep -E '^(rdb_changes_since_last_save|rdb_last_save_time|rdb_last_bgsave_status|aof_enabled|aof_last_write_status):'
rdb_changes_since_last_save:0
rdb_last_save_time:1791861317
rdb_last_bgsave_status:ok
aof_enabled:0
aof_last_write_status:ok

rdb_last_save_time is a Unix timestamp, the same value LASTSAVE returns. Turn it into something readable:

date -d @1791861317

What to look for:

  • rdb_last_bgsave_status:err: the last snapshot failed, and the Redis log says why. With the default stop-writes-on-bgsave-error yes, writes are now being refused:

    MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. Commands that may modify the data set are disabled...

    The usual causes are a full disk (the disk space triage helps), a dir that the redis user can’t write to, or a failed fork(). For that last one, the Redis FAQ’s answer is vm.overcommit_memory = 1. A snapshot forks the process, and with overcommit_memory at 0, Linux refuses the fork unless there’s enough free RAM to duplicate the whole dataset. If PostgreSQL shares the server, check what’s set before you change it (sysctl vm.overcommit_memory). PostgreSQL’s docs describe strict mode, 2, as a way to make the OOM killer less likely, so the two databases are pulling in different directions.

  • rdb_changes_since_last_save keeps climbing and the timestamp is old: snapshots aren’t triggering. Check redis-cli CONFIG GET save. An empty string means RDB is off.

  • aof_last_write_status:err: writes to the AOF are failing, usually because the disk is full.

To check one snapshot by hand, note LASTSAVE, run BGSAVE, and see whether LASTSAVE changes within a few seconds.

Prove the restore

A file that exists isn’t a backup until something has loaded it. The same idea drives the PostgreSQL restore drill, and Redis makes it cheap. Start a throwaway instance on another port with a copy of the snapshot:

mkdir -p /tmp/redis-restore
sudo cp /var/lib/redis/dump.rdb /tmp/redis-restore/
sudo chown "$USER" /tmp/redis-restore/dump.rdb
redis-check-rdb /tmp/redis-restore/dump.rdb
[offset 18188] Checksum OK
[offset 18188] \o/ RDB looks OK! \o/
[info] 1200 keys read

The tool really does celebrate. Now load the file:

redis-server --port 6390 --bind 127.0.0.1 --dir /tmp/redis-restore \
  --dbfilename dump.rdb --appendonly no --save "" --daemonize yes
redis-cli -p 6390 DBSIZE
redis-cli -p 6390 SHUTDOWN NOSAVE

--save "" and --appendonly no keep the test copy from writing anything, and SHUTDOWN NOSAVE makes sure it exits without saving either. DBSIZE should be close to what production reported when the snapshot was taken. Spot-check a few keys your app depends on, too. To test an AOF backup, copy the whole appendonlydir into the test directory, start with --appendonly yes, and check it first with redis-check-aof pointed at the manifest. Use the same redis-server binary as production for the test. Your backup should never be the first thing to meet a new version.

References

Cover photo: Unsplash.