Redis FLUSHALL ran in production: detection, prevention, and recovery

FLUSHALL deletes every key in every logical database. Under default save policies, the server typically triggers a background save of the empty keyspace within seconds, overwriting the RDB snapshot. There is no undo. If you are responding to an active incident, your priorities are: confirm the scope, isolate unaffected replicas before they process the flush, recover from the freshest intact persistence source, and harden the instance.

This guide covers verification, open recovery paths, execution, and post-incident hardening with rename-command and ACLs.

What this means

FLUSHALL removes all keys from all databases. FLUSHDB removes keys from the currently selected database. On Redis Cluster, FLUSHDB is equivalent to FLUSHALL because clusters use only database 0.

If save is active, the empty keyspace is typically snapshotted to RDB within seconds, overwriting the previous file. This destroys the on-disk fallback unless a filesystem snapshot or external backup predates the command.

The ASYNC modifier (Redis 4.0+) frees keys in the background, but the outcome is identical: every key present at invocation is deleted. Redis 6.2+ can default to ASYNC via lazyfree-lazy-user-flush yes; this does not prevent data loss.

If AOF is enabled, FLUSHALL is appended to the log. The pre-flush history survives until the next AOF rewrite, which produces an empty file because the in-memory dataset is empty.

Common causes

CauseWhat it looks likeFirst thing to check
Operator errorcmdstat_flushall shows a single call during a business-hours sessionACL LOG, shell history, and CLIENT LIST for recent admin connections
Application bugcmdstat_flushdb increments repeatedly, or loss is limited to one databaseApplication deployment logs and recent code changes
Compromised clientACL LOG shows auth failures followed by a flush from an unusual source IPSource address in CLIENT LIST or ACL LOG
Malicious actorSingle FLUSHALL followed by CONFIG SET or SAVEServer logs and INFO commandstats for surrounding commands

Quick checks

These are read-only and safe on a live instance.

# Confirm whether FLUSHALL or FLUSHDB has been called since server start
redis-cli INFO commandstats | grep -E "cmdstat_flushall|cmdstat_flushdb"

# Check current keyspace state across all databases
redis-cli DBSIZE
redis-cli INFO keyspace

# Inspect persistence file recency and AOF status
redis-cli INFO persistence | grep -E "rdb_last_save_time|rdb_current_bgsave_time_sec|aof_enabled"

# Check recent clients and authorization events
redis-cli SLOWLOG GET 10
redis-cli ACL LOG  # Redis 6.0+

On every replica, check immediately whether the flush has already been applied:

# Check if the replica still holds data
redis-cli DBSIZE
redis-cli INFO replication | grep master_link_status

How to diagnose the scope

  1. Confirm the command executed. INFO commandstats shows cumulative counters since server start. Any increase in cmdstat_flushall or cmdstat_flushdb means the command ran. Correlate with a sudden drop in DBSIZE or used_memory to confirm the impact.
  2. Determine whether it was FLUSHALL or FLUSHDB. cmdstat_flushall indicates total keyspace loss. cmdstat_flushdb indicates one logical database, but on Redis Cluster this is still total loss.
  3. Check RDB state. If rdb_last_save_time is very recent and the dump.rdb file on disk is small, the empty post-flush snapshot has already overwritten your previous backup.
  4. Check AOF status. If aof_enabled is 1 and no rewrite has run since the incident, the pre-flush data still exists in the AOF log. If aof_rewrite_in_progress is 1 or aof_current_size has collapsed to near-zero, the rewrite has already compacted the empty state and the AOF path is closed.
  5. Check replicas before they process the flush. Replication is asynchronous. A replica showing the expected DBSIZE and master_link_status:up has not yet processed the flush. Promote it immediately with REPLICAOF NO ONE if you intend to use it as a recovery source.
flowchart TD
  A[FLUSHALL or FLUSHDB executed] --> B{Check
cmdstat_flushall} B -->|calls increased| C[Check keyspace
DBSIZE / INFO keyspace] B -->|no increase| D[False alarm] C --> E{Replica still
has data?} E -->|yes| F[REPLICAOF NO ONE
Promote replica] E -->|no| G{AOF enabled
and not rewritten?} G -->|yes| H[Truncate AOF before
FLUSHALL command] G -->|no| I[Restore from external
filesystem snapshot] F --> J[Rebuild replication
topology] H --> K[Verify with
redis-check-aof] I --> L[Restart with
recovered RDB] J --> M[Apply hardening
ACLs / rename-command] K --> M L --> M

Recovery options

Recovery depends on which persistence layer the flush has not yet destroyed. Move fast: an AOF rewrite or scheduled RDB save will close the remaining paths.

From an unaffected replica

If a replica has not yet processed the flush, its dataset is intact. Verify with DBSIZE first.

Promote the replica to primary immediately:

# On the replica that still has data
redis-cli REPLICAOF NO ONE

On Redis < 5.0, use SLAVEOF NO ONE. After promotion, point other replicas at the new primary. Do not wait: the replica processes the flush the moment it reaches that offset in the replication stream.

From the last RDB snapshot

FLUSHALL overwrites the local RDB file with an empty snapshot, so the on-disk dump.rdb is unusable unless a filesystem-level snapshot (LVM, ZFS, EBS, or backup agent) predates the command.

To recover:

  1. Restore the pre-flush dump.rdb to the Redis data directory.
  2. If AOF is enabled, Redis prefers it over RDB on startup. To force loading the recovered RDB, either truncate the AOF before the flush or temporarily disable AOF.
  3. Restart. The instance enters a loading state until the dataset is restored.

From AOF

If AOF is enabled and no rewrite has run since the incident, the AOF contains every write up to and including FLUSHALL. Recovery requires truncating the AOF before the FLUSHALL entry.

redis-check-aof --fix only repairs corruption at the end of the file; it will not remove a valid FLUSHALL command from the middle. Manually truncate the AOF before the FLUSHALL entry, then verify integrity. If the truncation leaves an incomplete command at the end, use --fix to truncate at the last valid command. Restart Redis and confirm the dataset. If an AOF rewrite already ran after the flush, the compacted AOF is empty and this path is closed.

From external backup

If all local persistence paths are exhausted, restore from external backup (S3, object storage, or volume snapshots). Accept the data loss window since the last backup. After restoration, verify rdb_last_bgsave_status and aof_last_write_status before allowing writes.

Prevention

Rename or disable destructive commands

Use rename-command in redis.conf to disable FLUSHALL and FLUSHDB:

rename-command FLUSHALL ""
rename-command FLUSHDB ""

If an administrative tool legitimately requires the command, rename it to an obscure string instead of exposing the default name.

Restrict via ACLs

Redis 6.0+ supports per-user ACLs. Deny destructive commands for application users:

# Remove the entire dangerous category
ACL SETUSER appuser on >password ~* +@all -@dangerous

# Or explicitly deny the two commands
ACL SETUSER appuser on >password ~* +@all -flushall -flushdb

Reserve the default user for emergency access and rotate credentials regularly.

Monitor command statistics

These counters reset on server restart. Combine an alert on cmdstat_flushall/cmdstat_flushdb with a DBSIZE or used_memory drop to rule out a restart and confirm a genuine flush.

Operational hygiene

Do not allow applications or operators to connect to production Redis with superuser privileges by default. Use read-only accounts for troubleshooting, and restrict write access to the specific key patterns each application needs.

Metrics and signals to monitor

SignalWhy it mattersWarning sign
cmdstat_flushall / cmdstat_flushdbDirect evidence of destructive executionRate of increase > 0 outside maintenance windows
DBSIZE / INFO keyspaceDataset existenceSudden drop to near-zero
used_memoryMemory footprintSharp drop correlating with keyspace loss
rdb_last_save_timeRDB freshnessTimestamp newer than expected with empty dataset
master_link_status on replicasReplication healthReplicas still connected but about to process the flush
aof_current_sizeAOF growthSudden collapse after rewrite, or spike if flush appended

How Netdata helps

Netdata surfaces cmdstat_flushall, cmdstat_flushdb, used_memory, and keyspace trends so you can correlate command execution with dataset loss. It also tracks replication offset lag and link status to identify unaffected replicas, and persistence health (rdb_last_bgsave_status, aof_last_write_status) to confirm whether your on-disk fallbacks are intact.