Fix Redis MISCONF RDB Snapshot Errors in Django

Fix the Redis MISCONF error that blocks writes from Django and Celery: find why background saves fail (disk full, permissions, memory overcommit), restore writes safely, and decide whether the instance needs persistence at all.

Problem statement

Every cache write, session save, and Celery delay() suddenly fails with:

redis.exceptions.ResponseError: 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, because this instance is configured to report errors during writes
if RDB snapshotting fails (stop-writes-on-bgsave-error option).

Reads still work, so pages that only read the cache may load, while logins and checkouts fail. Redis forks a child to write its RDB snapshot; when that child fails, Redis refuses writes to protect you from believing data is persisted when it is not. The fix is to make the background save succeed again, not just to switch the safety check off.

Why Redis stops accepting writesBGSAVE startsfork a childChild failsdisk, perms, memorySafety checkstop-writes-on-errorWrites refusedMISCONF on every setRedis blocks writes because it can no longer guarantee the snapshot it promised.
  1. Read the Redis log for the line after Background saving started: it states the real error.
  2. Check disk space and the dir Redis writes to: redis-cli CONFIG GET dir and df -h.
  3. Check that the redis user owns that directory.
  4. If the fork fails with "Cannot allocate memory", set vm.overcommit_memory = 1.
  5. Run redis-cli BGSAVE and confirm rdb_last_bgsave_status:ok in INFO persistence.
  6. For a cache-only instance, disable RDB with save "" instead of ignoring errors.

Step-by-step solution

1. Find the real error

redis-cli INFO persistence | grep -E "rdb_last_bgsave_status|rdb_changes_since_last_save|rdb_last_bgsave_time_sec"
sudo journalctl -u redis-server --since "-2h" | grep -iE "save|fork|error"

The log line names the cause, for example:

  • Failed opening the temp RDB file temp-1234.rdb (in server root dir /var/lib/redis) for saving: Permission denied
  • Write error saving DB on disk: No space left on device
  • Can't save in background: fork: Cannot allocate memory

2. Fix disk space and the target directory

redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
df -h /var/lib/redis

If the disk is full, free space first; see Fix a Django Server With a Full Disk. An RDB write needs roughly as much free space as the dataset, because it writes a temp file before renaming it.

A common surprise: someone ran CONFIG SET dir /tmp or the config points at a directory that was cleaned up. Set it back and persist the config:

redis-cli CONFIG SET dir /var/lib/redis
redis-cli CONFIG REWRITE

If dir points somewhere odd that you did not set, treat it as a possible compromise: an exposed Redis without a password is commonly abused by rewriting dir and dbfilename. Bind Redis to private interfaces and require a password.

3. Fix ownership and permissions

ls -ld /var/lib/redis
sudo chown redis:redis /var/lib/redis
sudo chmod 750 /var/lib/redis

In Docker, the volume mounted at /data must be writable by the user the Redis image runs as (UID 999 in the official image).

what the Redis log saysLog messageCause and fixNo space left on devicedisk full; free space,keep 1x dataset freePermission denied on temp RDB filedir not owned by redis;chown the directoryfork: Cannot allocate memoryovercommit refused the fork;vm.overcommit_memory=1dir is /tmp or an odd pathconfig changed, possibly by anattacker; reset and lock downThe line after Background saving started names the real causedjango-deployment.com
Fix the cause, then trigger BGSAVE to prove snapshots work again.

4. Allow the fork to succeed

Redis forks a copy-on-write child to write the snapshot. With the default heuristic overcommit, the kernel can refuse a fork of a large process even though little extra memory is used in practice. Redis's own startup warning recommends:

echo "vm.overcommit_memory = 1" | sudo tee /etc/sysctl.d/90-redis.conf
sudo sysctl --system

Also make sure Redis has a maxmemory setting that leaves room for the rest of the server, and disable transparent huge pages if Redis warns about them, since they make copy-on-write much more expensive.

5. Restore writes and verify

redis-cli BGSAVE
sleep 5
redis-cli INFO persistence | grep rdb_last_bgsave_status

Once a background save succeeds, Redis accepts writes again automatically. If you need writes back immediately while you fix the cause, you can temporarily run redis-cli CONFIG SET stop-writes-on-bgsave-error no, but set it back to yes afterwards, or you will lose data silently the next time saves fail.

6. Decide whether this Redis needs RDB

A pure cache can be rebuilt from the database, so persistence is overhead. A Celery broker or session store usually should persist.

# cache-only instance
save ""
appendonly no
does this Redis need to survive a restart?What does Django store in this instance?cache onlyDisable RDBsave "" and no AOFsessionsRDB snapshotslosing minutes is acceptableCelery brokerAOF everysecplus RDB for backupsSeparate instances let each role have the persistence it needsdjango-deployment.com
A cache instance that never snapshots can never hit MISCONF.

Verification check: rdb_last_bgsave_status:ok, CONFIG GET stop-writes-on-bgsave-error returns yes, and a Django shell cache.set("probe", 1) succeeds.

Explanation

stop-writes-on-bgsave-error yes is a deliberate safety feature. If Redis kept accepting writes while every snapshot failed, a restart would lose everything since the last good snapshot without warning. By refusing writes, Redis turns a silent durability failure into a loud availability failure. That trade-off is right for data you care about and wrong for a disposable cache, which is why the cleaner fix for caches is to stop snapshotting rather than to ignore errors.

Edge cases / notes

  • Managed Redis handles persistence itself; MISCONF there usually means the plan is out of memory or disk. Contact the provider or scale up.
  • Docker containers without volumes write snapshots into the container layer, which can fill the host disk and is lost on recreate. Mount a volume at /data.
  • Large datasets make each fork slower and more memory-hungry. Watch rdb_last_bgsave_time_sec and latest_fork_usec.
  • Replicas also write RDB during full sync. A replica with a full disk breaks replication with similar errors.

Next steps

FAQ

Is it safe to set stop-writes-on-bgsave-error to no?

Only briefly while fixing the cause. Left off, a restart can lose data silently.

Why do reads still work?

MISCONF blocks commands that modify data. Reads are safe because nothing new needs persisting.

Does this affect Celery?

Yes. Queueing a task writes to Redis, so delay() fails until saves succeed again.

Do I need RDB for a cache?

No. Disable snapshots on cache-only instances.

Keep going