skip to content

Persistence: RDB & AOF

You will learn how an in-memory store survives restarts: point-in-time RDB snapshots, the append-only file with its fsync policies, and the hybrid that combines both. Interviewers use persistence to test whether you know exactly what data Redis can lose and what forking a multi-gigabyte process costs.

part ofRedisoverview, primer and where to startread it →
on this pageshow

explore

questions

22

What does the Redis append-only file (AOF) actually record, and what does turning on 'appendonly yes' give you that keeping only periodic point-in-time snapshots does not?

level: juniorimportance: must knowfreq 60%

answer

  1. log of write commands, RESP format
  2. appended AFTER execution
  3. SPOP→SREM, EXPIRE→PEXPIREAT (deterministic replay)
  4. grows with write volume, not dataset size
  5. recovery = re-execute the log

basics

~20 s

The AOF is a log of every write command that changed the dataset, appended after the command runs; recovery replays the commands. A snapshot only stores state as of the moment it was taken, so a crash loses everything since it — the AOF narrows that loss to a second or less.

solid answer

~50 s

With `appendonly yes`, every command that modifies the dataset is appended to a log file in the same RESP wire format clients use. Restart recovery means re-executing that log from the top, which rebuilds the dataset. Commands are logged **after** they execute, and in an *effect-normalised* form: non-deterministic commands are rewritten into deterministic ones, so `SPOP` becomes an `SREM` of the member actually popped and `EXPIRE` becomes `PEXPIREAT` with an absolute millisecond timestamp. Without that, a replay would produce a different dataset than the original run. The difference from snapshots is loss granularity. A snapshot captures the whole dataset at one instant, taken every few minutes, so a crash discards every write since the last one. The AOF is appended continuously, so with the default `appendfsync everysec` you lose roughly the last second. The costs are a bigger file, continuous disk writes, and slower startup — replay is re-executing every command.

code

text · 15 lines
text
# redis.conf
appendonly yes
appenddirname "appendonlydir"      # Redis 7.0+

# Client sends: SET user:1 ada
# AOF incremental file contains (RESP):
*3\r\n$3\r\nSET\r\n$6\r\nuser:1\r\n$3\r\nada\r\n

# Client sends: EXPIRE user:1 60
# AOF stores an ABSOLUTE deadline so replay is deterministic:
*3\r\n$9\r\nPEXPIREAT\r\n$6\r\nuser:1\r\n$13\r\n1786000000000\r\n

# Client sends: SPOP myset  -> returned "c"
# AOF stores the concrete effect:
*3\r\n$4\r\nSREM\r\n$5\r\nmyset\r\n$1\r\nc\r\n

go deeper

for a junior

Say what it is: a log of every write command, replayed on startup, giving a much smaller loss window than periodic snapshots.

for a middle

Add that entries are RESP-encoded and appended after execution, and that non-deterministic commands are normalised (SPOP→SREM, EXPIRE→PEXPIREAT) so replay reproduces the same dataset.

for a senior

Discuss the cost profile — growth proportional to write volume, continuous I/O, slower startup than a binary snapshot — and operational traps like CONFIG SET without CONFIG REWRITE, plus the 7.0 multi-part layout.

for a principal

Frame it as choosing a recovery-point objective and paying for it in I/O and restart time, and connect the same effect-normalisation to the replication stream so that durability and replica consistency are reasoned about together.

## What Redis is trying to solve Redis serves data from memory. If the process dies, memory is gone. Persistence exists so a restarted instance can rebuild the dataset. Redis offers two mechanisms with quite different shapes: a **snapshot** of the whole dataset (RDB), and an **operation log** of everything that changed it (AOF). This leaf is about the log. ## What the AOF contains When `appendonly yes` is set, every command that **modifies** the dataset is appended to the append-only log. Read commands are never logged — replaying a `GET` would change nothing. The entries are written in the **same RESP protocol encoding clients use**, which is why an AOF is human-readable: `SET user:1 ada` appears as a small array of bulk strings. Recovery is conceptually just "connect a fake client and feed it the file": Redis starts empty and re-executes the whole log. ## Logged after execution, not before This is a genuinely important detail and a favourite follow-up. Redis appends a command to the AOF **after** it has been executed successfully against the in-memory dataset, not before. Consequences: - A command that fails (wrong type, syntax error) never reaches the log, so a replay never re-runs a failure. - The log describes effects that definitely happened in memory — but a crash between execution and the durable write means an acknowledged effect can be missing from the file. That is precisely what the fsync policy governs. ## Effect normalisation: turning non-deterministic commands into deterministic ones Some commands do not produce the same result twice. `SPOP` removes a random member. `INCRBYFLOAT` depends on the current value. `EXPIRE key 60` means "sixty seconds from *now*", and "now" during a replay hours later is a different instant. So Redis rewrites such commands into a deterministic equivalent before appending them: - `SPOP myset` → `SREM myset <the member that was actually popped>` - `EXPIRE key 60` / `SETEX` → `PEXPIREAT key <absolute unix ms>` - `INCRBYFLOAT k 1.1` → `SET k <resulting value>` - Commands with random or time-dependent behaviour inside scripts are handled by propagating their effects rather than the script call. Without this, replay would silently diverge from the original dataset — a different random member removed, a key that should have expired still alive. The same normalisation feeds the replication stream to replicas. ## AOF versus snapshots: the real difference is the loss window A snapshot is a complete copy of the dataset at one instant, taken on a schedule (say every 5 minutes or every N changes). If the process dies four minutes after the last snapshot, four minutes of writes are gone — no matter how fast the disk is, because nothing was written for them. The AOF is appended continuously, so the exposure is the time between a write happening and that write reaching disk durably. With the default `appendfsync everysec`, that is about one second. With `appendfsync always`, the fsync happens before the client is told the command succeeded, so an acknowledged write survives a crash of that process. A useful way to phrase the distinction: a snapshot answers "what did the dataset look like at time T", the AOF answers "what happened, in order". The log's granularity is per command; the snapshot's is per schedule. ## What the AOF costs - **Size.** The file grows with the *volume of writes*, not with the size of the dataset. A single counter incremented a million times produces a million log entries for one key. (Redis solves that with a periodic rewrite that compacts the log into the minimal set of commands needed to recreate the current dataset — its own topic.) - **Continuous I/O.** Every event-loop cycle writes buffered commands to the file, and fsyncs happen per policy. - **Startup time.** Loading an AOF means re-executing every command through the normal command path, which is slower than loading a compact binary snapshot of the same dataset. ## Where it lives Since Redis 7.0 the AOF is not a single file but a **multi-part set** — a base file plus incremental files, tracked by a manifest, all inside the directory named by `appenddirname` (default `appendonlydir`) under `dir`. Before 7.0 it was one file named by `appendfilename`. The concept is unchanged; only the on-disk layout differs. ## Enabling and disabling it `appendonly yes` in the config file, or at runtime `CONFIG SET appendonly yes` (which triggers an initial rewrite to create the base). `CONFIG SET` is not persistent unless you also `CONFIG REWRITE` the config file — a classic operational surprise where durability silently disappears at the next restart. ## The interview-ready summary "The AOF logs every write command in RESP format, appended after execution and normalised so replay is deterministic; recovery re-executes the log. Compared with periodic snapshots it shrinks the crash-loss window from minutes to about a second, at the cost of a larger file, continuous writes, and slower startup."

  • Why does Redis rewrite SPOP as SREM in the AOF instead of logging SPOP itself?
    SPOP removes a random member, so replaying the literal command would very likely remove a different member than the original execution did, and the restored dataset would diverge from the one that crashed. Redis therefore logs the concrete effect — an SREM of the member actually removed. The same normalisation applies to time-dependent commands such as EXPIRE, which becomes PEXPIREAT with an absolute timestamp.
  • Does the AOF grow with the size of the dataset or with something else?
    With the volume of write traffic. One key that is incremented a million times generates a million log entries even though the dataset holds a single value, whereas a large dataset written once produces a small log. That is why the file must be periodically compacted into a minimal set of commands that recreates the current state, otherwise it grows without bound.
  • You ran CONFIG SET appendonly yes during an incident. Is the instance now durably configured?
    Only until it restarts. CONFIG SET changes the running server, not the config file, so the next restart comes back with appendonly no and no AOF at all. You must also run CONFIG REWRITE (or edit the config file) to make the change survive. This is a common way instances silently lose persistence weeks after an incident.

A snapshot is a photograph of the room every five minutes; the AOF is a running list of every object moved. The photo restores the room as of the photo; the list can rebuild it move by move.

saying these in an interview costs you the question

  • "The AOF stores the data / the values" — it stores the write commands, and the data is a replay of them.
  • "Commands are written to the AOF before they execute, like a write-ahead log" — Redis appends after execution.
  • "EXPIRE is logged verbatim" — it is normalised to PEXPIREAT with an absolute timestamp so replay is deterministic.
  • "AOF file size tracks dataset size" — it tracks write volume; a tiny dataset can produce a huge log.
  • "Turning on AOF makes writes durable immediately" — durability depends entirely on the fsync policy.

context

open as a page

Redis offers both a `SAVE` and a `BGSAVE` command for writing a snapshot to disk. What is the difference between them, and why is one of them effectively forbidden on a production server?

level: juniorimportance: must knowfreq 55%

basics

~20 s

SAVE writes the snapshot on the main thread, so the server answers no commands until it finishes — unusable in production. BGSAVE forks a child that writes the snapshot while the parent keeps serving; only the brief fork itself pauses the server.

open as a page

Redis exposes three values for the appendfsync setting: always, everysec and no. What does each one do, and how much data does each risk losing when the process or the machine crashes?

level: middleimportance: must knowfreq 66%

basics

~20 s

always fsyncs before replying, so an acknowledged write survives a crash, at a big throughput cost. everysec (the default) fsyncs once per second in a background thread, risking about a second of writes. no never fsyncs — the OS flushes when it likes, so a machine crash can lose tens of seconds.

open as a page

Redis can be configured to append every write command to an append-only file (AOF). What does the BGREWRITEAOF command do, and why does an append-only log need rewriting at all?

level: middleimportance: must knowfreq 58%

basics

~20 s

The AOF records every write, so it grows with write volume and repeats history. BGREWRITEAOF forks a child that writes a new minimal file reproducing the current in-memory dataset, then atomically swaps it in: smaller file, faster restart.

open as a page

Redis has a configuration directive called `aof-use-rdb-preamble`. What does enabling it change about the append-only file Redis writes and reads, and what do you gain from it?

level: middleimportance: must knowfreq 45%

basics

~20 s

With it on, a rewritten append-only file starts with the whole dataset in compact binary snapshot format, then appends later write commands as normal text. One file, snapshot body plus command tail. You gain much faster loading and a smaller file; durability is unchanged.

open as a page

A Redis instance is configured with snapshot persistence only — no append-only file. If the host loses power, how much data is lost, and what exactly determines that amount?

level: middleimportance: must knowfreq 48%

basics

~20 s

Everything written since the last completed snapshot. The amount is set by the configured save points, how long each save takes, and the write rate — so it ranges from seconds to the longest save-point interval, potentially an hour.

open as a page

Redis runs an append-only-file (AOF) rewrite in a forked child process, the same way a background RDB snapshot (BGSAVE) does. Setting aside the generic cost of fork() and copy-on-write, what is different about an AOF-rewrite child in production, and which Redis INFO fields and LATENCY monitor events would you watch to observe one?

level: seniorimportance: must knowfreq 48%

basics

~20 s

An AOF-rewrite child lives far longer than a BGSAVE on the same data, and the parent keeps writing AOF to the same disk throughout. Watch latest_fork_usec, aof_rewrite_in_progress, aof_rewrite_scheduled, aof_last_bgrewrite_status, aof_last_cow_size, and LATENCY LATEST's fork event.

open as a page

A client sends a write to Redis and receives an OK reply. What has actually been guaranteed at that instant, and what would you have to add for "this write is safe" to hold end-to-end — through the Redis process, the operating system page cache, the storage device, and other nodes?

level: seniorimportance: must knowfreq 50%

basics

~20 s

An OK from Redis means only that the command was applied in the master's memory. Safety is a ladder: process memory, OS page cache, the device (whose own cache can lie), another node. The WAIT and WAITAOF commands confirm replication or fsync after the fact, not synchronously.

open as a page

How would you take a backup of a Redis dataset that you can actually restore from, and what does the restore procedure look like?

level: seniorimportance: must knowfreq 44%

basics

~20 s

Use RDB as the backup artifact: trigger BGSAVE (ideally on a replica), copy dump.rdb off-host with a timestamped name and retention. Restore by stopping the server, placing the file in dir, starting with appendonly no, then enabling AOF at runtime. Verify by actually restoring.

open as a page

A Redis process holding about 8 GB of data momentarily grows toward 16 GB of resident memory whenever a background snapshot runs, and the host occasionally OOM-kills it. Explain the mechanism behind that growth and what you would change to stop the kills.

level: seniorimportance: must knowfreq 55%

basics

~20 s

The snapshot child is a fork() sharing memory copy-on-write. Every page the parent writes during the save gets duplicated, so a write-heavy instance can approach double its size. Fix with memory headroom (maxmemory well under RAM), disabled transparent huge pages, vm.overcommit_memory=1, and snapshotting from a replica.

open as a page

A Redis server is configured with both snapshotting and the append-only file enabled, and it restarts. Which of the two files does it use to rebuild the dataset, and what goes wrong if someone enables the append-only file by editing the config file and restarting?

level: juniorimportance: should knowfreq 40%

basics

~20 s

If appendonly yes, Redis loads the append-only file and ignores the snapshot, because the AOF is more current. Turning AOF on by editing the config and restarting loads an empty AOF, so the server comes up empty and can overwrite the snapshot.

open as a page

Redis can start an append-only-file rewrite on its own. Explain how the auto-aof-rewrite-percentage and auto-aof-rewrite-min-size settings decide when that happens, and what baseline size the growth is measured against.

level: middleimportance: should knowfreq 42%

basics

~20 s

Redis remembers the AOF size after the last rewrite (or at startup). When the current size exceeds that baseline by auto-aof-rewrite-percentage (default 100, meaning doubled) and is at least auto-aof-rewrite-min-size (default 64mb), it starts a rewrite. Percentage 0 disables it.

open as a page

A `redis.conf` contains the lines `save 3600 1`, `save 300 100` and `save 60 10000`. Explain precisely what those lines make the server do, and what changes if you replace them all with `save ""`.

level: middleimportance: should knowfreq 45%

basics

~20 s

Each line is a save point: snapshot in the background if at least that many key changes happened within that many seconds. They are OR-ed, so any satisfied line triggers one. save "" disables automatic snapshots; manual BGSAVE and replica sync still work.

open as a page

A team documents that their Redis instance can lose at most one second of writes because it runs with 'appendfsync everysec'. Under what circumstances is that claim wrong, and how would you detect it on a running instance?

level: seniorimportance: should knowfreq 30%

basics

~20 s

If the background fsync is still running when the next write is due, Redis postpones the write for up to about two seconds rather than blocking, so the unsynced window can reach ~2s. And with no-appendfsync-on-rewrite yes, fsyncs stop entirely during a rewrite. Check aof_delayed_fsync in INFO persistence.

open as a page

After switching a Redis instance to 'appendfsync always', p99 latency for all clients jumps and occasionally the whole instance appears to freeze for tens of milliseconds. How do you confirm the AOF sync path is the cause, and what are your options?

level: seniorimportance: should knowfreq 28%

basics

~20 s

With always, an fsync runs in the serving path each event-loop cycle, so every client pays the device's sync latency. Confirm with the latency monitor's aof-fsync-always and aof-write events plus INFO persistence, and device I/O stats. Options: faster local storage, back to everysec, or move the guarantee to replicas.

open as a page

Before Redis 7.0, a rewrite of the append-only file required buffering writes that arrived while the child worked and appending them at the end. What did Redis 7.0's multi-part AOF change, and which problems did it solve?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Redis 7 replaced the single appendonly.aof with a directory holding a base file (RDB-format by default), one or more incremental files, and a manifest. The parent writes concurrent commands into a new incremental file instead of an in-memory rewrite buffer, so the buffer and the final diff-append are gone.

open as a page

Your Redis server refuses to start, logging that the append-only file is bad after an unclean shutdown. Walk through how you diagnose and repair it, including what the redis-check-aof --fix tool actually does.

level: seniorimportance: should knowfreq 34%

basics

~20 s

Copy the file first. Distinguish a truncated tail (tolerated by default via aof-load-truncated) from mid-file corruption, which always blocks startup. redis-check-aof --fix truncates from the first invalid command to end of file, discarding everything after it. For RDB, redis-check-rdb only verifies; it cannot repair.

open as a page

On Redis 7.x the append-only file is a directory (default `appendonlydir`) containing a `.manifest` file, a base file, and one or more `.incr.aof` files. As the operator: what is the unit you must copy or restore, how does the server decide what to load at startup, where do you point `redis-check-aof`, and what breaks if a script copies or truncates one file inside that directory on its own?

level: seniorimportance: should knowfreq 24%

basics

~20 s

The copy unit is the whole directory — manifest plus the base file plus every incr file it names, as one consistent set. Startup reads the manifest and loads base first, then incr files in manifest order. Point redis-check-aof at the manifest. A single file copied or truncated in isolation gives an unloadable or silently short dataset.

open as a page

Redis snapshot files are a compact binary format rather than a log of write commands. What operational advantages does that format buy, and where does it constrain you?

level: seniorimportance: should knowfreq 35%

basics

~20 s

A snapshot is a compressed, checksummed image that loads by deserialization instead of replaying millions of commands, so restarts and replica seeding are fast and the file is small enough to copy off-box. The costs: not human-readable or editable, and version-coupled on downgrade.

open as a page

You operate a 60 GB Redis instance with append-only-file persistence, and append-only-file rewrites cause periodic latency spikes and near-out-of-memory events. How would you decide when and how rewrites should happen?

level: principalimportance: should knowfreq 26%

basics

~20 s

Decide with two budgets: acceptable fork-stall latency and acceptable restart time. Then choose among fewer rewrites (raise the percentage or disable auto and schedule off-peak), moving persistence to a replica, and sharding so no node maps 60 GB. Fix the host first: overcommit on, huge pages off.

open as a page

A team wants to use Redis as the system of record for data with monetary value. What durability posture would you configure, and what would you tell them they can still lose?

level: principalimportance: should knowfreq 24%

basics

~20 s

Set AOF on with everysec or always, snapshots shipped off-host, and replicas in separate failure domains. Then state the residual risk plainly: asynchronous replication means a failover can discard acknowledged writes, so money needs reconciliation against a durable source elsewhere.

open as a page

You operate three Redis deployments: a page-fragment cache, a user session store, and a small ledger of business events that no other system holds. For each, decide whether to run snapshots only, the append-only file only, or both — and justify the configuration you would set.

level: principalimportance: should knowfreq 40%

basics

~20 s

Cache: snapshots only, or nothing — data is rebuildable. Sessions: both, with the append-only file on everysec, since losing minutes of logins hurts but is survivable. Ledger: both, with a real replica and off-box backups, because Redis alone should not be the system of record.

open as a page