skip to content

RDB Snapshots

You will learn how BGSAVE forks the process and relies on copy-on-write to snapshot memory to a compact binary file while serving traffic. Interviewers ask because the fork's memory spike and the between-snapshots loss window are the two costs candidates forget.

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

questions

5

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%

answer

  1. SAVE = blocks the single thread, outage
  2. BGSAVE = fork + copy-on-write child
  3. only pause is fork, see latest_fork_usec
  4. temp file then atomic rename
  5. MISCONF: failed bgsave can block writes

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.

solid answer

~50 s

Both produce the same `dump.rdb` file; they differ in who does the work. `SAVE` serializes the dataset **on the main thread**. Redis executes commands one at a time on a single thread, so for the whole duration — seconds to minutes on a large dataset — every client is blocked and every request queues. On a live server that is an outage. `BGSAVE` calls `fork()`. The child inherits a copy-on-write view of memory and writes the snapshot from it, while the parent immediately goes back to serving commands. The only stall is the fork itself, whose cost scales with the size of the process's page tables — typically milliseconds to tens of milliseconds per gigabyte, and worse on virtualized hardware. Automatic save points always use `BGSAVE`. `SAVE` survives for scripted maintenance where the server is already quiet and you want to be certain the file is complete before the process exits.

code

text · 9 lines
text
$ redis-cli LASTSAVE
(integer) 1723640112
$ redis-cli BGSAVE
Background saving started
$ redis-cli INFO persistence | grep -E 'rdb_bgsave_in_progress|rdb_last_bgsave_status'
rdb_bgsave_in_progress:0
rdb_last_bgsave_status:ok
$ redis-cli LASTSAVE      # advanced => the new snapshot is on disk
(integer) 1723640119

go deeper

for a junior

State clearly that SAVE blocks every client until it finishes and BGSAVE forks a child so the server keeps serving, and that automatic saves use BGSAVE.

for a middle

Add the mechanism: fork, copy-on-write child, temp file plus atomic rename, and the fork pause as the one real stall.

for a senior

Bring in latest_fork_usec, copy-on-write memory growth versus write rate, the single-child restriction, and MISCONF write rejection after a failed save.

for a principal

Discuss when snapshotting belongs on the primary at all — moving it to a replica, sizing memory headroom for copy-on-write, and treating fork pauses as part of the instance's latency budget.

## What a snapshot is An RDB snapshot is a point-in-time binary image of the entire dataset — every key, its value in the internal encoding, and its expiration — written to the file named by `dbfilename` inside `dir` (by default `dump.rdb`). It is compact, optionally LZF-compressed, and carries a CRC64 checksum so a truncated or corrupted file is detected on load. Redis has two commands to produce one on demand, plus automatic save points that use the background form. ## `SAVE`: synchronous, on the main thread Redis processes client commands on a single thread. `SAVE` performs the serialization inline on that thread. Until the last byte is written, the server executes nothing else: clients block, the accept queue backs up, health checks time out, and any monitoring that speaks Redis reports the instance as down. On a 10 GB dataset that is not a hiccup, it is an outage of tens of seconds or more. The upside of that same property is determinism: when `SAVE` returns `OK`, the file on disk is complete and no further writes have been applied. That makes it occasionally useful in a maintenance script on an instance that is already drained — for instance, before deliberately killing a process on a box you are decommissioning. Redis also performs a blocking save on `SHUTDOWN` when save points are configured, for exactly this reason. ## `BGSAVE`: fork a child `BGSAVE` returns immediately with `Background saving started`. Under the hood Redis calls `fork()`. The child process gets a logically identical copy of the parent's memory, implemented by the kernel as **copy-on-write**: nothing is duplicated up front, page tables are marked read-only, and a page is only copied when one side writes to it. The child then walks that frozen view and writes the RDB to a temporary file; on success it renames the temp file over `dump.rdb`, which is atomic on the same filesystem, so a crash mid-save leaves the *previous* snapshot intact. The parent, meanwhile, keeps serving. The one unavoidable pause is `fork()` itself, which must copy the page tables — cost proportional to how much memory the process maps, commonly on the order of ten-ish milliseconds per gigabyte on bare metal and noticeably worse on some virtualized instances. `INFO stats` reports the last one as `latest_fork_usec`, and it is one of the first things to check when a user reports a periodic latency spike. The less obvious cost is memory: because the parent keeps taking writes, every page it modifies during the save gets copied, so resident memory grows during the snapshot in proportion to the write rate and the save duration. ## Concurrency and status Only one child of this kind runs at a time. If a `BGSAVE` is already running, another `BGSAVE` is refused; if an AOF rewrite is running, Redis will typically defer a save point rather than fork twice. Useful fields from `INFO persistence`: - `rdb_bgsave_in_progress` — 1 while a child is writing - `rdb_last_bgsave_status` — `ok` or `err` - `rdb_last_save_time` — Unix time of the last successful save (also returned by `LASTSAVE`) - `rdb_changes_since_last_save` — how many writes are currently unprotected A scripted snapshot usually reads `LASTSAVE`, issues `BGSAVE`, and polls `LASTSAVE` until it advances — that is the non-blocking equivalent of waiting for `SAVE` to return. ## Failure behavior worth knowing If the background save fails — full disk, permissions, fork denied for lack of memory — `rdb_last_bgsave_status` becomes `err`, and with the default `stop-writes-on-bgsave-error yes` Redis begins **rejecting write commands** with a `MISCONF` error. This surprises people badly: the instance is up, reads work, writes fail. It is deliberate, on the reasoning that a server configured to persist should tell you loudly when it no longer can. On a pure cache, where persistence is a nicety, setting it to `no` is defensible; on a store of record, fix the disk instead. ## Summary line for an interview Same output, different execution: `SAVE` blocks the single command thread for the whole write; `BGSAVE` forks and writes from a copy-on-write child, paying only the fork pause plus copy-on-write memory. Automatic save points use `BGSAVE`; `SAVE` belongs in maintenance scripts on quiet instances.

  • If `BGSAVE` does not block the server, what is the cost of running it?
    Three things. The `fork()` call itself pauses the main thread for a time proportional to the process's page tables (visible as `latest_fork_usec`). Copy-on-write means memory grows during the save in proportion to the write rate, so a write-heavy instance can approach double its resident size. And the child competes for disk I/O and CPU, which can add latency on a saturated box.
  • How does a script know a background save actually finished successfully?
    Record `LASTSAVE` before issuing `BGSAVE`, then poll `LASTSAVE` until the timestamp advances — it only moves on a successful save. Cross-check `rdb_last_bgsave_status:ok` and `rdb_bgsave_in_progress:0` in `INFO persistence`. Do not assume success just because `BGSAVE` returned, since it returns as soon as the child is forked.
  • What happens to the existing dump.rdb if the server is killed while a background save is running?
    It survives untouched. The child writes to a temporary file and only renames it over `dump.rdb` after writing the complete image, and the rename is atomic within a filesystem. A crash mid-save therefore leaves you with the previous complete snapshot rather than a half-written one.

SAVE is closing the shop to take inventory; BGSAVE is photographing the shelves and counting from the photo while customers keep shopping.

saying these in an interview costs you the question

  • Claiming `BGSAVE` runs on a background thread — it is a forked process, not a thread
  • Saying `SAVE` is fine because it is fast on a small dataset, without acknowledging it blocks all clients
  • Thinking `BGSAVE` has no cost at all on the main thread (the fork pause is real)
  • Assuming the child sees writes made after the fork — the snapshot is the state at fork time
  • Not knowing that a failed background save can start rejecting writes with MISCONF

context

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

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.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

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