Persistence¶
Moon supports two persistence mechanisms: RDB point-in-time snapshots and AOF (append-only file) write-ahead logging. Both can be used together.
AOF (recommended)¶
AOF logs every write operation to per-shard WAL files. This is the recommended persistence method for durability.
Fsync policies¶
| Policy | Durability | Performance |
|---|---|---|
always |
Every write fsynced | Highest durability, lowest throughput |
everysec |
Fsync every second | Good balance (recommended) |
no |
OS-controlled flush | Highest throughput, risk of data loss |
Per-shard WAL advantage¶
Unlike Redis's single global AOF file, Moon writes a separate WAL per shard. This eliminates the global serialization bottleneck:
| Pipeline depth | Moon vs Redis (with AOF) |
|---|---|
| p=1 | 0.95x (parity) |
| p=16 | 2.21x |
| p=64 | 2.75x |
The advantage grows with pipeline depth because each shard appends independently with no lock contention.
WAL v3 format¶
Moon uses WAL v3 (src/persistence/wal_v3/; v2 was removed) with:
- Segmented files (16MB default, --wal-segment-size) with a 64-byte
header carrying epoch, redo LSN, and base LSN
- Per-record LSNs — the foundation for PITR and CDC cursors
- Checksums for corruption detection
- Full-page images (FPI) with lz4 compression for torn-page recovery
- Corruption isolation per shard (one shard's corruption does not affect others)
- Off-loop fsync — a per-shard sync agent thread owns the fsync so the
shard event loop never blocks on durability waits
The hot-path cost of WAL append is ~5ns (buf.extend_from_slice()), with batch write_all every 1ms tick and fsync on the configured schedule.
One KV log at a time (--wal-kv-log)¶
With --appendonly yes the AOF is the crash-recovery authority: startup
replays the AOF over a wiped keyspace, discarding whatever the WAL replayed
first. Moon therefore skips the WAL copy of each KV command by default
(--wal-kv-log auto) — one durable KV log instead of two, halving on-disk
write volume at --shards >= 2 with zero recovery loss. The WAL still carries
checkpoint/FPI and feature records, and KV logging re-engages automatically
when a CDC subscriber attaches. Set --wal-kv-log on if you need
point-in-time recovery or full CDC history alongside the AOF.
âš The WAL is not a standalone durability log. With
--appendonly no, only cross-shard (SPSC-dispatched) writes reach the WAL — writes local to a connection's own shard are not logged anywhere, so crash recovery loses roughly1/num_shardsof writes at--shards >= 2(measured: 79% recovered at 4 shards) and everything at--shards 1. Keep--appendonly yes(the default) whenever you need KV durability; the WAL's KV stream exists for CDC, PITR, and disk-offload — not as an AOF replacement.
RDB snapshots¶
RDB creates point-in-time snapshots of the entire dataset.
# Auto-save: snapshot after 3600 seconds if at least 1 key changed,
# or after 300 seconds if at least 100 keys changed
./target/release/moon --save "3600 1 300 100" --dir /var/lib/moon
# Manual trigger
redis-cli BGSAVE
Forkless snapshots¶
Moon uses forkless compartmentalized snapshots instead of Redis's fork() approach. This means:
- No copy-on-write memory spike (Redis can temporarily double memory usage during BGSAVE)
- DashTable segments are iterated asynchronously
- Snapshot runs alongside normal operations without blocking
Using both¶
For maximum durability, enable both AOF and RDB:
./target/release/moon \
--appendonly yes \
--appendfsync everysec \
--save "3600 1 300 100" \
--dir /var/lib/moon
AOF provides point-of-failure recovery, while RDB provides compact backups for disaster recovery or cloning.