AOF: The Append-Only Log
If RDB is a “Save Game” feature, then AOF (Append Only File) is the “Replay” feature.
Instead of taking a snapshot of the memory, AOF logs every single write command (like SET, INCR, LPUSH) that Redis receives.
When Redis restarts, it simply re-plays this log from start to finish to reconstruct the dataset.
1. Why AOF?
RDB snapshots are great, but they have a flaw: Data Loss Window. If you snapshot every 5 minutes and Redis crashes at minute 4:59, you lose 4 minutes and 59 seconds of data.
AOF solves this by logging writes as they happen.
2. The Cost of Durability: fsync Policies
Writing to disk is slow. Writing to memory is fast. If Redis wrote to disk synchronously for every command, it would be terribly slow.
Redis uses the OS buffer cache and the fsync system call to balance speed and safety. You control this with the appendfsync configuration:
| Policy | Description | Performance | Safety |
|---|---|---|---|
always |
Call fsync after every write command. |
🐢 Very Slow | ✅ Zero Data Loss |
everysec |
Call fsync once per second (Default). |
🚀 Fast | ⚠️ 1 Second Loss |
no |
Let the OS decide when to flush (usually every 30s). | 🚀🚀 Fastest | ❌ High Risk |
[!TIP] Use
everysec. It is the default for a reason. You get near-memory performance, and in the worst-case crash (power failure), you lose only 1 second of data.
3. The Problem: The Log Grows Forever
If you run INCR counter 1 million times, your AOF file will contain 1 million entries.
INCR counter
INCR counter
INCR counter
...
But the final state is just counter = 1000000. We only need one command to restore it: SET counter 1000000.
This is where AOF Rewrite comes in.
Interactive: AOF Rewrite Visualizer
See how Redis compacts the AOF log. Enter a sequence of commands and watch the rewrite process eliminate redundant operations.
Original AOF Log (Size: 0 bytes)
Rewritten AOF (Size: 0 bytes)
4. Configuring AOF in Production
You typically enable AOF in redis.conf:
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
Automatic Rewrite
Redis automatically triggers a rewrite when the AOF file grows too large.
# Rewrite if AOF size is 100% larger (2x) than the last rewrite size
auto-aof-rewrite-percentage 100
# ... but only if the file is at least 64MB
auto-aof-rewrite-min-size 64mb
5. AOF in Java & Go
package main
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
// Trigger BGREWRITEAOF
status := rdb.BgRewriteAOF(ctx)
if err := status.Err(); err != nil {
panic(err)
}
fmt.Println("Rewrite started:", status.Val())
}
6. RDB vs AOF: The Verdict
| Feature | RDB | AOF |
|---|---|---|
| Durability | Low (Minutes lost) | High (1 second lost) |
| File Size | Compact (Binary) | Large (Text logs) |
| Startup Speed | Fast | Slow (Replay takes time) |
| Integrity | Robust | Can be corrupted (fixable) |
Can we have the best of both worlds? Yes. That is what we will cover in the next chapter: Hybrid Persistence.