How to back up and restore Redis (RDB and AOF)
Run redis-cli --rdb /var/backups/redis/dump.rdb to pull a fresh snapshot from a running Redis, or copy dump.rdb from the data directory, which is safe at any time because Redis replaces it atomically. To restore, stop Redis first, put the file in place, and start it with appendonly matching the backup: a running Redis overwrites a swapped-in file when it stops, and an enabled AOF takes precedence over dump.rdb.
Does your Redis need a backup?
| What Redis holds | Back it up? |
|---|---|
| A cache the app rebuilds from its database | Usually not. Losing it costs a few slow minutes, not data. |
| Sessions | Yes, unless logging every user out is acceptable. |
| Job queues | Yes. Queued emails, payments and webhooks exist nowhere else. |
| Primary data: counters, leaderboards, feature flags | Yes. |
If maxmemory-policy is an allkeys- policy, Redis already evicts any key when memory runs short, so it is a cache by design. A replica is not a backup: a FLUSHALL or a bad deploy reaches it at once.
RDB, AOF, or both
| Mode | What is on disk | What a crash loses |
|---|---|---|
| RDB | dump.rdb, a compact point-in-time snapshot written by the save rules | Every write since the last snapshot |
| AOF | A log of every write. Since Redis 7, a directory of base and incremental files plus a manifest | About one second with the default appendfsync everysec |
| Both | Both of the above | As AOF. At startup Redis loads the AOF and ignores dump.rdb. |
With aof-use-rdb-preamble yes, the default, the AOF base file is itself RDB, named like appendonly.aof.1.base.rdb. Ubuntu's package ships appendonly no and the built-in save rules: snapshot after 3600 seconds if 1 key changed, 300 seconds if 100 did, or 60 seconds if 10000 did.
redis-cli CONFIG GET savesave
3600 1 300 100 60 10000Find the files
Ask Redis where it writes. With Ubuntu's package, dir is /var/lib/redis, owned by the redis user.
redis-cli CONFIG GET dirredis-cli CONFIG GET dbfilenameredis-cli CONFIG GET appendonlyappenddirname (default appendonlydir) names the AOF directory inside dir. Redis 7 refuses to change dir or dbfilename at runtime with can't set protected config; change them in redis.conf and restart.
Take a snapshot: BGSAVE, SAVE and LASTSAVE
BGSAVE forks a child that writes the snapshot while Redis keeps serving clients. It replies Background saving started at once, not when the save finishes.
redis-cli BGSAVELASTSAVE returns the Unix time of the last successful save; poll it until it changes. Right after startup it returns the start time, even if nothing was saved.
date -d @$(redis-cli LASTSAVE)INFO persistence shows whether a save is running and whether the last one worked:
redis-cli INFO persistence | grep -E 'rdb_changes_since_last_save|rdb_bgsave_in_progress|rdb_last_save_time|rdb_last_bgsave_status|aof_enabled|aof_rewrite_in_progress'rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1791053222
rdb_last_bgsave_status:ok
aof_enabled:0
aof_rewrite_in_progress:0A second BGSAVE fails with ERR Background save already in progress. On Redis 7.0, BGSAVE SCHEDULE only queues behind an AOF rewrite and returned the same error during another BGSAVE. SAVE blocks every client until it finishes; the Redis docs keep it as a last resort for when the fork fails.
Fork and memory
The fork shares memory with Redis through copy-on-write: every page written to during the save gets copied. A write-heavy instance needs spare RAM beyond used_memory, and rdb_last_cow_size in INFO persistence shows how much the last save copied. latest_fork_usec in INFO stats shows how long the fork paused Redis; on large datasets it can reach a second.
With the kernel's default overcommit setting, Redis logs WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. at startup. Our test instance did. The fix Redis gives in that message is vm.overcommit_memory = 1 in /etc/sysctl.conf, applied at once with sudo sysctl vm.overcommit_memory=1.
Copy the RDB file safely
Copying dump.rdb while Redis runs is safe: Redis writes each snapshot to a temporary file such as temp-1531026.rdb and renames it over dump.rdb only when complete. It is only as fresh as the last save, so run BGSAVE and wait for LASTSAVE to change first.
redis-cli --rdb does both in one step. It asks for a fresh snapshot over the replication protocol and writes it locally, even from a remote server with -h:
redis-cli --rdb /var/backups/redis/redis-now.rdbIt forks like BGSAVE, waits about five seconds by default before starting, prints Transfer finished with success after 597997 bytes, and exits 0. On failure it exits 1, which suits scripts.
If Redis has a password, pass it in the REDISCLI_AUTH environment variable. -a works but puts the password in the process list, and redis-cli warns: Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
For ordinary commands, redis-cli exits 0 even when Redis replies with an error. In our tests, ERR Background save already in progress and NOAUTH Authentication required. both came back with exit code 0. In scripts, add -e so errors exit 1, or use --rdb.
Back up the AOF directory (Redis 7)
Since Redis 7.0 the AOF is several files in appenddirname, tied together by a manifest. After one rewrite, ours looked like this:
sudo ls /var/lib/redis/appendonlydirappendonly.aof.2.base.rdb
appendonly.aof.2.incr.aof
appendonly.aof.manifestsudo cat /var/lib/redis/appendonlydir/appendonly.aof.manifestfile appendonly.aof.2.base.rdb seq 2 type b
file appendonly.aof.2.incr.aof seq 2 type iCopy the whole directory, manifest included. A rewrite can swap files mid-copy, so the Redis docs say to pause rewrites first:
- Note the current value with
redis-cli CONFIG GET auto-aof-rewrite-percentage(100 on Ubuntu), then runredis-cli CONFIG SET auto-aof-rewrite-percentage 0. - Wait until
redis-cli INFO persistenceshowsaof_rewrite_in_progress:0. - Hard-link the files into a folder on the same filesystem:
sudo mkdir /var/lib/redis/aof-snapthensudo sh -c 'ln /var/lib/redis/appendonlydir/* /var/lib/redis/aof-snap/'(your own shell cannot expand the*inside theredis-only directory). - Turn rewrites back on:
redis-cli CONFIG SET auto-aof-rewrite-percentage 100. - Archive the links and remove them:
sudo tar -czf /var/backups/redis/aof-$(date +%F).tar.gz -C /var/lib/redis/aof-snap .thensudo rm -r /var/lib/redis/aof-snap.
Even with AOF on, an RDB snapshot from BGSAVE or --rdb is a complete, simpler backup. Back up the AOF directory to restore straight into an AOF server.
Restore an RDB backup
Stop Redis before touching its files. On Ubuntu:
sudo systemctl stop redis-serversudo sh -c 'gunzip -c /var/backups/redis/redis-2026-10-03_0315.rdb.gz > /var/lib/redis/dump.rdb'sudo chown redis:redis /var/lib/redis/dump.rdbsudo systemctl start redis-serverredis-cli INFO keyspace# Keyspace
db0:keys=20004,expires=0,avg_ttl=0Never replace dump.rdb while Redis runs. With save rules on, as Ubuntu ships, Redis saves on shutdown. We swapped in a 3-key backup and stopped Redis the way systemd does; it logged Saving the final RDB snapshot before exiting. and overwrote our file with the 20,002 keys in memory.
If appendonly yes is set, Redis loads the AOF and ignores dump.rdb. With no AOF directory present, our restore started with 0 keys and logged Creating AOF base file appendonly.aof.1.base.rdb on server start.
To restore an RDB into a server that uses AOF:
- Stop Redis and move the old AOF aside:
sudo mv /var/lib/redis/appendonlydir /var/lib/redis/appendonlydir.old. - Set
appendonly noin/etc/redis/redis.conf, putdump.rdbin place as above, and start Redis. - Run
redis-cli CONFIG SET appendonly yes. Redis writes a new AOF from memory. - Wait until
INFO persistenceshowsaof_rewrite_in_progress:0andaof_last_bgrewrite_status:ok. - Set
appendonly yesinredis.confagain, so the next restart keeps AOF on.
To restore an AOF backup, stop Redis, replace appendonlydir with the extracted archive, chown -R redis:redis it, and start with appendonly yes. In our test it loaded the AOF even with an older dump.rdb beside it.
Restore onto the same Redis version or newer. Redis 7.0 writes RDB format 10 (the file starts with REDIS0010), and Redis stops with Can't handle RDB format version when a file is newer than it understands.
Verify a backup
redis-check-rdb, in the redis-tools package, reads the whole file and checks its checksum. A good file ends like this:
redis-check-rdb /var/backups/redis/redis-now.rdb[offset 597914] Checksum OK
[offset 597914] \o/ RDB looks OK! \o/
[info] 20002 keys read
[info] 0 expires
[info] 0 already expiredOn a copy cut in half it printed --- RDB ERROR DETECTED --- and Unexpected EOF reading RDB file, and exited 1. For AOF backups, point redis-check-aof at the manifest; it ends with All AOF files and manifest are valid.
redis-check-aof /var/lib/redis/appendonlydir/appendonly.aof.manifestThe real test is loading it. Put the backup in an empty directory as dump.rdb, start a throwaway Redis on another port, and compare key counts:
redis-server --port 6390 --bind 127.0.0.1 --dir /tmp/restore-test --save "" --appendonly no --daemonize yesredis-cli -p 6390 INFO keyspaceredis-cli -p 6390 shutdown nosaveUse INFO keyspace, not DBSIZE, which counts only the current database: ours said 20004 while INFO keyspace also listed db3:keys=1. See how to test a backup restore.
Automate it with cron
This script pulls a fresh snapshot, checks it, compresses it, and deletes copies older than seven days. A failed transfer or damaged file stops it before anything is renamed.
sudo install -d -m 700 /var/backups/redis#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/var/backups/redis"
KEEP_DAYS=7
OUT="$BACKUP_DIR/redis-$(date +%Y-%m-%d_%H%M).rdb"
# Holds REDISCLI_AUTH if Redis has a password
[ -f /etc/redis-backup.env ] && . /etc/redis-backup.env
trap 'rm -f "$OUT.partial"' EXIT
redis-cli -p 6379 --rdb "$OUT.partial"
redis-check-rdb "$OUT.partial" > /dev/null
mv "$OUT.partial" "$OUT"
gzip "$OUT"
find "$BACKUP_DIR" -name 'redis-*.rdb.gz' -type f -mtime +"$KEEP_DAYS" -deleteexport REDISCLI_AUTH='your-redis-password'sudo chmod 600 /etc/redis-backup.envsudo chmod 700 /usr/local/bin/redis-backup.sh15 3 * * * root /usr/local/bin/redis-backup.sh >> /var/log/redis-backup.log 2>&1For queues or sessions, run it hourly (15 * * * *). A copy on the same disk dies with the server, so ship the directory off-site with rclone. More in how to schedule backups with cron.
Common errors
| Error | Fix |
|---|---|
MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. | The last background save failed and Redis now refuses writes. The log line before Background saving error says why: a full disk, permissions, or no memory to fork. Fix the cause and run BGSAVE; turning off stop-writes-on-bgsave-error only hides it. |
ERR Background save already in progress | Wait until rdb_bgsave_in_progress:0, then retry. |
NOAUTH Authentication required. | Redis has a password. Export REDISCLI_AUTH before calling redis-cli. |
can't set protected config | dir and dbfilename cannot change at runtime in Redis 7. Edit redis.conf and restart. |
Short read or OOM loading DB. Unrecoverable error, aborting now. | The RDB file is incomplete, and Redis refuses to start. Check backups with redis-check-rdb and restore an earlier one. |
| Redis starts with 0 keys after a restore | appendonly yes made Redis ignore dump.rdb. Follow the AOF restore steps above. |
WARNING Memory overcommit must be enabled! | Set vm.overcommit_memory = 1 so background saves do not fail to fork. |
Apps that keep their data in SQLite instead need SQLite's own tools to copy it safely: see how to back up a SQLite database.
Frequently asked questions
- Is it safe to copy dump.rdb while Redis is running?
- Yes. Redis writes snapshots to a temporary file and renames it into place when complete, so dump.rdb is always whole, though only as recent as the last save.
- What is the difference between SAVE and BGSAVE?
- SAVE blocks every client until the snapshot is written. BGSAVE forks a child to write it while Redis keeps serving. Use BGSAVE.
- Does BGSAVE block Redis?
- Only during the fork: usually milliseconds, up to about a second for a very large dataset. latest_fork_usec in INFO stats shows yours.
- Do I need to back up Redis if it is only a cache?
- Usually not, if the app rebuilds it from its database. Back it up if it holds sessions, job queues or data found nowhere else.
- Can I restore an RDB file on a different Redis version?
- On the same version or newer, yes. An older Redis refuses an RDB format it does not know.
How this was checked
The commands were run on Ubuntu 24.04 LTS, Redis 7.0.15 on October 3, 2026. Any that need something this test server does not have, such as a second server, a cloud account or another database engine, were checked against the official pages below instead.
Sources, on October 3, 2026: