Valkey’s Append-Only File (AOF) can become a bottleneck if not tuned correctly, but often the most impactful tuning isn’t about appendfsync at all.
Let’s see Valkey’s AOF in action. Imagine a simple scenario: we’re writing a few keys and then reading them back.
# Start Valkey with AOF enabled (default config is fine for now)
valkey-server --port 6379 --appendonly yes
# In another terminal, connect with redis-cli
redis-cli -p 6379
# Perform some writes
127.0.0.1:6379> SET key1 "value1"
QUEUED
127.0.0.1:6379> SET key2 "value2"
QUEUED
127.0.0.1:6379> SET key3 "value3"
QUEUED
127.0.0.1:6379> MSET key4 "value4" key5 "value5"
QUEUED
# Read back
127.0.0.1:6379> GET key1
"value1"
127.0.0.1:6379> MGET key4 key5
1) "value4"
2) "value5"
# Check AOF status (will show file size)
127.0.0.1:6379> INFO persistence
# Persistence
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_aof_file_size:215
aof_base_size:198
aof_current_size:215
aof_current_size_other_threads:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0
The AOF file (appendonly.aof by default) logs every write operation received by the server. When Valkey restarts, it replays this log to reconstruct the dataset. This ensures durability: if Valkey crashes, no committed writes are lost.
The core of AOF performance tuning revolves around how frequently Valkey syncs the AOF buffer to disk. This is controlled by the appendfsync directive in valkey.conf. The options are:
appendfsync always: Every write command is fsync’d to disk. This offers the highest durability but is the slowest.appendfsync everysec: The AOF buffer is written to disk once per second. This is the default and a good balance between durability and performance. Writes are buffered in memory and fsync’d in a background thread.appendfsync no: The operating system decides when to fsync. This is the fastest but offers the least durability; you could lose up to a second of data on a crash.
Beyond appendfsync, several other factors significantly impact AOF performance:
- Disk I/O Subsystem: The speed of your storage is paramount. Even with
appendfsync no, a slow disk will be a bottleneck. NVMe SSDs are vastly superior to HDDs for AOF. - AOF Rewriting: As the AOF file grows, it can become inefficient. Valkey periodically performs an AOF rewrite, which creates a new, smaller AOF file containing only the current state of the dataset. This is done in the background. If rewrites are too frequent or too slow, they can contend with normal write operations.
- Diagnosis: Monitor
aof_rewrite_in_progressandaof_last_bgrewrite_time_secinINFO persistence. Checkvalkey-cli --eval scripts/slowlog.lua 10000 <valkey_host> <valkey_port>to see if rewrite commands are taking a long time. - Tuning: Adjust
auto-aof-rewrite-min-size(default 64MB) andauto-aof-rewrite-percentage(default 100). Increasingauto-aof-rewrite-min-sizemeans the AOF file has to grow larger before a rewrite is considered. Loweringauto-aof-rewrite-percentagetriggers rewrites more aggressively. - Why it works: Rewrites reduce the AOF file size, meaning fewer writes to disk during the rewrite process and a faster startup time.
- Diagnosis: Monitor
no-appendfsync-on-rewrite: When set toyes(default), Valkey skipsfsynccalls during an AOF rewrite. This significantly speeds up the rewrite process itself, but at the cost of potentially losing data written during the rewrite if Valkey crashes.- Diagnosis: If
aof_rewrite_in_progressis often1and you suspect I/O contention, this is a candidate. - Tuning: In
valkey.conf, setno-appendfsync-on-rewrite yes. - Why it works: During a rewrite, the AOF buffer is written to a temporary file. Normally,
fsyncwould be called on this temporary file. By skipping it, the rewrite completes much faster, reducing the window of potential data loss and I/O impact on the main server.
- Diagnosis: If
aof-use-rdb-preamble: When enabled (default isyes), Valkey writes an RDB preamble to the AOF file. This allows Valkey to load the AOF file faster after a restart by loading the RDB part first, then applying the incremental changes.- Diagnosis: If startup times after restarts are unexpectedly long and you’re using AOF, this is worth investigating.
- Tuning: In
valkey.conf, setaof-use-rdb-preamble no. - Why it works: Disabling this means Valkey will only read the AOF commands during startup, avoiding the RDB loading step. This can be faster if the RDB part is very large and the AOF changes are minimal, but generally, the default is preferred.
append-direct: (Requires Valkey compiled withHAVE_LINUX_AIO) If enabled, Valkey uses Linux AIO forfsyncoperations, bypassing the kernel’s page cache. This can improve performance by reducing I/O overhead and ensuring data is written directly to disk.- Diagnosis: If you’re on a Linux system with AIO support and experiencing persistent AOF I/O issues, this is a potential optimization.
- Tuning: In
valkey.conf, setappend-direct yes. - Why it works: Direct I/O can offer more predictable performance and bypass potential bottlenecks within the kernel’s page cache management, especially under heavy write loads.
The most common performance issue with AOF isn’t the appendfsync setting itself, but rather the contention caused by frequent or slow AOF rewrites impacting foreground operations.
If you’ve tuned your AOF settings and are still seeing performance issues, the next problem you’ll likely encounter is memory fragmentation.