1. Overview
Redis provides two complementary data persistence mechanisms to survive restarts and failures: RDB snapshots and AOF (Append Only File). Thus far we have learnt many features in Redis that are helpful in building performant services, but our service would easily break down without data persistence.
Understanding how each works and how they combine is helpful for building a highly available Redis deployment.
2. RDB Snapshot
An RDB file is a compact, point-in-time binary snapshot of the entire dataset. Redis can create RDB files either manually or automatically by two commands:
2.1.Manual Trigger: SAVE and BGSAVE
Manual Trigger: SAVE and BGSAVE
SAVE The SAVE command performs a synchronous snapshot. While the RDB file is being written, Redis blocks all client request, no reads or writes are served until the file is complete. This makes SAVE unsuitable for production use.
BGSAVE The BGSAVE command is the production-safe alternative. When being invoked, Redis calls the fork() system function from glibc to create a child process. The child process takes ownership of the snapshot operation and writes the RDB file to disk, while the parent process continues to serve client requests without interruption.
fork() The fork() call itself is extremely fast, typically measured in milliseconds, so the blocking window for the main thread is negligible. All the time-consuming I/O work happens in the child process.
2.2.Auto Trigger: Four Occasions that Invoke BGSAVE
Auto Trigger: Four Occasions that Invoke BGSAVE
Redis can be configured to trigger BGSAVE automatically under the following four conditions:
-
save m ninredis.conf— when withinmseconds at leastnkeys get modified,BGSAVEis triggered automatically. For example,save 900 1means: trigger a snapshot if at least 1 key changes within 900 seconds. -
Replication — when a replica (slave) requests a full
resyncfrom the master, the master executesBGSAVEto generate an RDB file and sends it to the replica. -
DEBUG RELOAD— this command instructs Redis to reload its dataset from disk, and it triggersBGSAVEbeforehand to ensure the on-disk snapshot is current. -
SHUTDOWNwithout AOF — when Redis receives aSHUTDOWNcommand and AOF persistence is disabled, Redis automatically callsBGSAVEto preserve the current state before shutting down.
To disable RDB snapshots entirely, set the following in redis.conf:
2.3.RDB Configuration Options
RDB Configuration Options
| Config Key | Purpose |
|---|---|
dbfilename dump.rdb | Sets the filename of the RDB snapshot file |
dir /var/lib/redis | Sets the directory where the RDB file is stored |
stop-writes-on-bgsave-error yes | If BGSAVE fails, Redis stops accepting write commands to signal the problem. Set to no to allow writes regardless of snapshot failures |
rdbcompression yes | Compresses string values in the RDB file using LZF compression, reducing file size at the cost of some CPU |
rdbchecksum yes | Appends a CRC64 checksum to the RDB file. Redis verifies this on load to detect file corruption, at a ~10% performance cost |
2.4.Copy-On-Write (COW)
Copy-On-Write (COW)
After fork(), both the parent and child processes initially share the same physical memory pages. No data is duplicated at this point. When the parent process handles a write request that modifies a memory page, the operating system makes a private copy of that page for the parent — the child retains the original. This is the Copy-On-Write mechanism.
The practical consequence is that the child process sees a consistent, frozen snapshot of the data at the time of the fork, even as the parent continues serving writes. Redis does not need to lock or pause its dataset to achieve this consistency.
2.5.Advantages and Limitations of RDB
Advantages and Limitations of RDB
RDB is compact and fast to restore — Redis simply loads the binary file into memory on startup, which is much faster than replaying a log. RDB also produces small files that are easy to transfer or back up.
However, RDB is not suitable for real-time data persistence. Because snapshots are taken at intervals, any writes that occur after the last BGSAVE and before a crash are permanently lost. The gap can range from seconds to minutes depending on configuration.
3. AOF (Append Only File)
AOF addresses the persistence gap left by RDB. Instead of snapshotting the dataset, Redis records every write command as it is executed by appending it to the AOF log file. On restart, Redis replays the log from the beginning to reconstruct the dataset.
AOF is disabled by default. To enable it, set the following in redis.conf:
3.1.appendfsync — Controlling Flush Frequency
appendfsync — Controlling Flush Frequency
The appendfsync option in redis.conf controls how often Redis flushes the in-memory AOF buffer to disk:
| Option | Behaviour |
|---|---|
always | Flushes to disk after every write command. Maximum durability, but lowest throughput |
everysec | Flushes to disk once per second (default). At most one second of data can be lost on crash |
no | Delegates flushing to the OS. Highest throughput, but data loss window is entirely OS-controlled |
For most deployments, everysec offers the best balance between safety and performance.
3.2.AOF Rewrite: Compactifying the Log
AOF Rewrite: Compactifying the Log
Over time, the AOF file grows without bound. Many commands in the log may become redundant — for instance, setting the same key a hundred times only requires the final state to restore correctly.
AOF-rewrite compatifies the file by scanning the current in-memory dataset and writing the minimal set of commands needed to reproduce the same result from scratch. This is triggered either manually or automatically.
To trigger it manually:
To configure automatic AOF-rewriting in redis.conf:
-
auto-aof-rewrite-percentage 100means: trigger a rewrite when the AOF file has grown by 100% relative to its size at the last rewrite (i.e., doubled in size). -
auto-aof-rewrite-min-size 64mbensures the rewrite only triggers once the AOF file is at least 64 MB, preventing frequent rewrites on small datasets.
The rewrite is handled by a child process spawned via fork(). The only moment the main thread is blocked is during the fork itself — which, as noted for BGSAVE, is negligible. All subsequent rewrite I/O happens in the child.
3.3.The Two-Buffer Problem During Rewrite
The Two-Buffer Problem During Rewrite
While the child process rewrites the AOF in the background, the parent continues to accept write commands. There are now two AOF files in play:
- The old AOF file (still on disk, being actively appended to) and
- The new compacted AOF file the child is in the process of building.
These incoming write commands must not be lost, but they cannot go into the new compacted AOF file — because the child started from a frozen snapshot of memory at the moment of fork(), and its output file is meant to faithfully represent exactly that snapshot. Mixing in new writes would break that consistency.
To handle this, Redis maintains two buffers simultaneously during a rewrite:
-
aof_buf— the regular AOF buffer, which continues flushing to the current (old) AOF file as usual. Every incoming write still flows through here normally. -
aof_rewrite_buf— a secondary buffer. Every incoming write is also mirrored here so that no commands are lost after the child's snapshot point.
When the child finishes writing the new compacted AOF file, the parent appends the contents of aof_rewrite_buf to it, then atomically replaces the old AOF file. This ensures no writes are lost, but it also means every write during the rewrite period is written to two buffers.
3.4.Multi-Part AOF in Redis 7.0
Multi-Part AOF in Redis 7.0
The two-buffer approach above introduces a dual-write overhead: every write command that arrives while a rewrite is in progress must be written twice:
- Once into
aof_buf(flushed to the old AOF file) and - Once into
aof_rewrite_buf(held in memory).
This doubles the write amplification for every incoming command during the rewrite window, increasing both memory usage and CPU cost.
Redis 7.0 introduced Multi-Part AOF to eliminate this overhead. The AOF is split into three logical components:
- Base AOF. A single file representing the compacted baseline state, equivalent to the output of a rewrite.
- Incr AOF. Receives all new write commands appended incrementally since the last rewrite.
- History AOF. Old base and incr files from previous rewrite cycles, kept briefly before being cleaned up.
During a rewrite, the child writes a new Base AOF. Meanwhile, new writes from the parent go only into a fresh Incr AOF — there is no secondary rewrite buffer. Once the child finishes, the new Base AOF and the current Incr AOF together represent the complete dataset. This eliminates the need to write incoming commands to two buffers, reducing both memory pressure and I/O overhead.
3.5.Advantages and Disadvantages of AOF
Advantages and Disadvantages of AOF
Advantages:
- Much lower data loss risk — at most one second of commands (with
everysec), or none (withalways). - The log is human-readable and can be manually inspected or edited to recover from accidental operations.
Disadvantages:
- AOF files are larger than RDB files for the same dataset.
- Restart recovery by replaying the log is slower than loading an RDB binary.
- Write throughput can be lower, particularly with
alwaysmode.
4. Hybrid Persistence (Redis 4.0+)
From Redis 4.0 onwards, it is possible to combine both mechanisms. When AOF rewrite runs with hybrid persistence enabled, the child process writes the current dataset as a compact RDB snapshot into the beginning of the new AOF file, followed by any incremental AOF commands appended after the snapshot. The result is a single file that starts with an RDB block and ends with an AOF log.
To enable hybrid persistence:
Note that the default value of aof-use-rdb-preamble differs by version: it defaults to no in Redis 4.0 and must be set explicitly, while from Redis 5.0 onwards it defaults to yes. Since AOF itself (appendonly) is still disabled by default in all versions, on Redis 5.0+ we only need to turn AOF on — hybrid persistence comes along automatically without any extra configuration.
On restart, Redis detects the RDB preamble and loads it rapidly into memory (benefiting from RDB's fast restore), then replays only the AOF tail to apply commands that arrived after the last snapshot. This gives the best of both worlds: fast startup from the RDB portion and minimal data loss from the AOF portion.
The recovery priority on startup is:
- If AOF is enabled and the AOF file exists, Redis uses it (with the RDB preamble if hybrid mode is on).
- If AOF is disabled but an RDB file exists, Redis loads the RDB file.
- If neither file exists, Redis starts with an empty dataset.






