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
| Cause | What it looks like | First thing to check |
|---|---|---|
| Operator error | cmdstat_flushall shows a single call during a business-hours session | ACL LOG, shell history, and CLIENT LIST for recent admin connections |
| Application bug | cmdstat_flushdb increments repeatedly, or loss is limited to one database | Application deployment logs and recent code changes |
| Compromised client | ACL LOG shows auth failures followed by a flush from an unusual source IP | Source address in CLIENT LIST or ACL LOG |
| Malicious actor | Single FLUSHALL followed by CONFIG SET or SAVE | Server 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
- Confirm the command executed.
INFO commandstatsshows cumulative counters since server start. Any increase incmdstat_flushallorcmdstat_flushdbmeans the command ran. Correlate with a sudden drop inDBSIZEorused_memoryto confirm the impact. - Determine whether it was FLUSHALL or FLUSHDB.
cmdstat_flushallindicates total keyspace loss.cmdstat_flushdbindicates one logical database, but on Redis Cluster this is still total loss. - Check RDB state. If
rdb_last_save_timeis very recent and thedump.rdbfile on disk is small, the empty post-flush snapshot has already overwritten your previous backup. - Check AOF status. If
aof_enabledis 1 and no rewrite has run since the incident, the pre-flush data still exists in the AOF log. Ifaof_rewrite_in_progressis 1 oraof_current_sizehas collapsed to near-zero, the rewrite has already compacted the empty state and the AOF path is closed. - Check replicas before they process the flush. Replication is asynchronous. A replica showing the expected
DBSIZEandmaster_link_status:uphas not yet processed the flush. Promote it immediately withREPLICAOF NO ONEif 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 --> MRecovery 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:
- Restore the pre-flush
dump.rdbto the Redis data directory. - 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.
- Restart. The instance enters a
loadingstate 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
| Signal | Why it matters | Warning sign |
|---|---|---|
cmdstat_flushall / cmdstat_flushdb | Direct evidence of destructive execution | Rate of increase > 0 outside maintenance windows |
DBSIZE / INFO keyspace | Dataset existence | Sudden drop to near-zero |
used_memory | Memory footprint | Sharp drop correlating with keyspace loss |
rdb_last_save_time | RDB freshness | Timestamp newer than expected with empty dataset |
master_link_status on replicas | Replication health | Replicas still connected but about to process the flush |
aof_current_size | AOF growth | Sudden 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.
Related guides
- How Redis actually works in production: a mental model for operators
- Redis aof_last_write_status:err: AOF write failures and recovery
- Redis appendfsync always latency: durability vs throughput trade-offs
- Redis big keys: finding the giant key that blocks the event loop
- Redis blocked_clients growing: dead consumers vs healthy queues
- Redis BUSY Redis is busy running a script: blocking Lua and how to recover
- Redis Can’t save in background: fork: Cannot allocate memory - diagnosis and fix
- Redis client output buffer overflow: slow consumers and client-output-buffer-limit
- Redis cluster_slots_pfail > 0: impending node failure in a cluster
- Redis CLUSTERDOWN / cluster_state:fail: slot coverage and recovery
- Redis connected_clients climbing: connection leak detection
- Redis connected_slaves dropped: detecting replica disconnects on the primary







