Redis MISCONF RDB Snapshot — Disk Fix and Persist
Fix Redis MISCONF by freeing disk, fixing permissions, and restarting persistence.
20+ years shipping high-throughput database systems. Lessons pulled from things that broke in production.
- ✓A Redis server (5+) with redis-cli access
- ✓Shell access to check disk and dir ownership
- ✓Know your save/appendonly settings and data dir
- MISCONF means Redis can't persist RDB snapshots (disk full, permissions, no space) and, with stop-writes-on-bgsave-error yes, it refuses writes rather than risk silent data loss
- Confirm with INFO persistence: rdb_last_bgsave_status:err plus rdb_last_bgsave_time_sec tells you background saves are failing — then check df -h and the dir ownership
- Fix the cause (free disk, chown the data dir, clear the failing volume), then restart persistence with BGSAVE and verify LASTSAVE advances and status returns to ok
- For durability without fork storms, enable AOF (appendonly yes) alongside RDB — and never leave stop-writes disabled as the 'fix'
Picture a cashier whose register refuses new sales because the end-of-day journal can't be filed — the filing cabinet is full (disk) or locked (permissions). MISCONF is that refusal: Redis stops taking writes rather than silently losing your data. The remedy is emptying the cabinet (free disk), unlocking it (fix ownership), and filing again (BGSAVE) — then proving the journal advances (LASTSAVE). A second journal method (AOF) means one stuck drawer never halts the whole shop again.
MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk. Commands that may modify the data set are disabled. It appears during the night nobody watches: logs fill the volume, a deploy changes the data-dir owner, or a forked bgsave hits memory pressure — and Redis chooses safety over availability, refusing writes until persistence works again.
That refusal surprises teams: the server is up, reads work, RAM looks fine — but every write fails. The stop-writes-on-bgsave-error yes default is deliberate protection: without it, Redis would accept writes it can no longer snapshot, turning a disk problem into silent data-loss exposure on restart.
This guide diagnoses through INFO persistence, fixes disk and permission causes, restarts snapshots cleanly, handles the stop-writes flag honestly, adds AOF as a second durability leg, and monitors persistence so the next failure pages before writes halt. The same drill covers every node type — primaries, replicas, and sentinels alike.
Read the Error and the Persistence State
MISCONF names the policy (configured to save, currently unable) and the consequence (writes disabled) — but not the cause. INFO persistence supplies it: rdb_last_bgsave_status ok/err, rdb_last_bgsave_time_sec (-1 means never failed... actually time of last attempt), rdb_changes_since_last_save (how much is at risk), and rdb_bgsave_in_progress. Pair with LASTSAVE (Unix timestamp of the last good snapshot): err status plus a LASTSAVE hours old is a failing snapshotter, full stop.
Read the server log for the one-line cause BGSAVE prints on failure: 'Failed opening the RDB file dump.rdb for saving: Permission denied' (EACCES — ownership/mount), versus 'Can't save in background: fork: Cannot allocate memory' (memory/overcommit), versus write errors mid-save (ENOSPC). Each maps to a different section below, so capture the line before acting — the fix for permissions does nothing for a full disk.
Record the risk number too: rdb_changes_since_last_save counts writes since the last good snapshot, i.e., your exposure if the box dies now. Thousands of changes reframes the incident from 'writes halted' to 'writes halted AND prior writes unsnapshotted' — which sets the urgency for the disk fix versus the flag workaround correctly.
Disk Full or Permissions: The Two Usual Causes
ENOSPC arrives via sharing: app logs, journald, or backups on the same volume as dump.rdb, growing until the next forked save finds zero bytes. Diagnose with df -h on the CONFIG GET dir path (not / — Redis may live on a dedicated mount whose fullness root's df hides among healthy lines), then du-sort the volume to name the hog. Reclaim non-Redis bytes only: stale logs, vacuumed journals, orphaned temps. dump.rdb and appendonly files are recovery assets, never cleanup candidates.
EACCES arrives via ownership: config management, manual chowns, or container volume mounts leaving the data dir root-owned or read-only. ls -ld plus ls -l on the dir and file name it; chown -R redis:redis plus mode 750 repairs it; /proc/mounts reveals read-only mounts needing remounts. The deploy that broke ownership will re-break it nightly unless its template is fixed — audit the config management diff, not just the directory.
Fork failures are the third, rarer cause: Cannot allocate memory on huge instances without overcommit tuning (vm.overcommit_memory=1). BGSAVE needs copy-on-write headroom proportional to write churn during the save; check the log line, set overcommit, and consider active defrag plus smaller save frequencies for multi-GB instances. Memory-cause MISCONF masquerades as disk — the log line distinguishes them.
The stop-writes Flag: Protection, Not Punishment
stop-writes-on-bgsave-error yes is the default for a reason: it converts silent durability loss into a loud, pageable write halt. With the flag on, a failed snapshot stops writes — painful, visible, recoverable. With it off, Redis accepts writes it cannot snapshot, and a subsequent crash loses everything since the last good save with no prior warning. The flag doesn't cause the incident; it announces the incident that already happened.
Use CONFIG SET stop-writes-on-bgsave-error no strictly as a timeboxed bridge: writes resume while you fix the disk in the same window, incident stays open, revert within the hour via CONFIG SET ... yes plus CONFIG REWRITE. Document the window in the ticket with timestamps — 'flag off 22:04, disk fixed 22:31, flag on 22:32' — so the next review sees a controlled bridge, not a casual dismissal of durability.
Never accept 'leave it off' as the resolution, from anyone, for any convenience argument. Guides recommending permanent disable trade real durability for uptime theater: green dashboards over a snaptureless server. The correct permanent fix is always working persistence — disk, permissions, memory — with the flag on, verified by LASTSAVE advancing.
Restart Persistence After the Fix
With cause fixed, restart the snapshotter deliberately: BGSAVE (expect 'Background saving started'), then poll LASTSAVE until the timestamp advances past the incident window. An advancing LASTSAVE is the only proof that matters — config reads and log optimism don't count. Confirm INFO persistence flips rdb_last_bgsave_status to ok and rdb_changes_since_last_save resets toward zero as the fresh snapshot absorbs the backlog.
If BGSAVE fails again immediately, re-read the log line — the second failure often differs from the first (permissions fixed, now ENOSPC from the backlog's fork needs; or the temp file colliding). Fix forward through each distinct cause; each BGSAVE attempt prints exactly one. Two different failures in sequence is normal progress, not a new incident.
Persist any config changes with CONFIG REWRITE so restarts keep them — runtime SETs evaporate on restart, and a failover that resurrects the old broken dir or the disabled flag reopens the incident on the new primary. Verify the rewritten redis.conf contains the corrected dir, dbfilename, and flag before closing the ticket. A failover that resurrects stale config reopens the incident on the new primary within hours.
AOF Fallback: Durability Without Fork Storms
AOF (append-only file) logs every write and rewrites compactly on schedule — second-granularity durability (appendfsync everysec) without RDB's fork-per-save cost profile. Enabling it beside RDB gives two independent recovery legs: snapshots for fast restarts, logs for fine-grained replay. When RDB fork pressure (huge instance, write churn) is itself the MISCONF cause, AOF carries durability while you retune snapshot frequency.
Enable online: CONFIG SET appendonly yes starts logging immediately; BGREWRITEAOF compacts the initial bulk; CONFIG REWRITE persists both. Expect steady I/O (everysec fsync) instead of bursty fork load — size the volume's IOPS for the stream, not the snapshot. Monitor aof_last_rewrite_time_sec and aof_last_bgrewrite_status exactly like their RDB twins; a second leg needs the same watchdog.
Keep both legs monitored and tested: restart drills that recover from RDB, point-in-time replays from AOF, and corruption checks (redis-check-aof) quarterly. An untested durability leg is a hope, and hopes don't restore sessions at 2 AM. Two legs, both watched, both drilled — that is the posture that survives disks, forks, and failures together every single time without exception.
Prevention: Disk Alerts, Backups, and Replicas
Isolate persistence onto its own volume at provisioning: dump.rdb, AOF, and temp files share one disk sized for snapshots plus growth — never with app logs, never with backups staging. Alert at 75% with a 24-hour growth projection (df trends, not just thresholds); a volume filling 2 GB/day pages days before ENOSPC, not minutes. Logrotate configs for anything near Redis get monitored checksums — the incident's root cause was a silently disabled rotator.
Watch the full persistence triad per node: disk %, rdb_last_bgsave_status, and LASTSAVE age (stale beyond 2× the save interval pages). A cron watchdog over redis-cli INFO plus df covers all three in ten lines and pages before writes halt — the 12 green minutes of read-only health checks never recur. Cover replicas identically: a replica that can't persist restarts empty, and Sentinel won't warn you.
Ship snapshots off-box: rdb backups to object storage hourly, AOF segments with the same cadence, restore drills monthly. On-box persistence protects against crashes; off-box copies protect against everything else — volume loss, AZ failure, the rm -rf that no flag can stop. Durability is a chain from fork to off-box copy, and every link gets a monitor.
Log Rotation Lapsed and Filled the Redis Volume in 25 Minutes
- Never share Redis persistence volumes with logs: a 2 GB/day leak becomes a 25-minute write outage exactly when nobody watches — isolate dump.rdb and AOF on their own disk.
- Monitor persistence state, not just process liveness: read-only health checks stayed green through a total write halt — watch rdb_last_bgsave_status, LASTSAVE age, and disk %.
- Fail over the cause, not the symptom: the replica shared the volume pattern and failed identically — diagnose INFO persistence plus df before triggering elections.
| File | Command / Code | Purpose |
|---|---|---|
| persistence_state.sh | redis-cli -h cache-01 INFO persistence | grep -E \ | Read the Error and the Persistence State |
| disk_perm_fix.sh | redis-cli -h cache-01 CONFIG GET dir | Disk Full or Permissions |
| stopwrites_bridge.sh | redis-cli -h cache-01 CONFIG GET stop-writes-on-bgsave-error | The stop-writes Flag |
| restart_persist.sh | redis-cli -h cache-01 BGSAVE | Restart Persistence After the Fix |
| aof_fallback.sh | redis-cli -h cache-01 CONFIG SET appendonly yes | AOF Fallback |
| watch_persist.sh | set -euo pipefail | Prevention |
Key takeaways
Common mistakes to avoid
5 patternsFailing over instead of reading persistence state
Leaving stop-writes disabled permanently
Deleting dump.rdb to free space
Health-checking reads only
Sharing the persistence volume with logs
Interview Questions on This Topic
What does Redis MISCONF mean?
Frequently Asked Questions
20+ years shipping high-throughput database systems. Lessons pulled from things that broke in production.
That's Redis. Mark it forged?
5 min read · try the examples if you haven't