configure and read it with intent
Redis runs as a single-threaded event loop, where every slow command blocks all other clients at once. The slowlog logs exactly these commands with timestamp, duration, and arguments, making it the most direct tool for tracing a latency problem back to a specific command instead of a vague guess.
Table of contents
- 1. What the slowlog is and what it is for
- 2. SLOWLOG GET, LEN, and RESET in detail
- 3. Correctly configuring slowlog-log-slower-than
- 4. slowlog-max-len and the ring buffer behavior
- 5. Identifying blocking commands: KEYS, SORT, FLUSHALL
- 6. Interpreting slowlog entries: timestamp, duration, client
- 7. From diagnosis to fix: SCAN instead of KEYS and SORT alternatives
- 8. Integrating the slowlog into your monitoring pipeline
- 9. Limits of the slowlog and the latency monitor as a complement
- 10. Summary
- 11. FAQ
1. What the slowlog is and what it is for
The slowlog is a ring buffer built into Redis that logs every command whose execution time exceeds a configurable threshold. Because Redis internally runs as a single-threaded event loop, every slowly executed command blocks all other clients for its entire runtime, regardless of how many connections are active. The slowlog makes exactly those blocking moments visible that would otherwise only appear as diffuse latency spikes in monitoring.
It is important to understand what the slowlog actually measures: not the entire round-trip time including network latency, but exclusively the time the command took to execute inside the Redis engine itself. An entry in the slowlog therefore always means the server itself was blocked for that duration, making it the most precise available tool for distinguishing server-side performance problems from pure network issues.
2. SLOWLOG GET, LEN, and RESET in detail
SLOWLOG GET returns the logged entries, ten by default, where a number as a parameter controls the count and SLOWLOG GET -1 returns every stored entry. Each entry contains a unique, monotonically increasing ID, a Unix timestamp, the execution duration in microseconds, the full command arguments, and since Redis 4.0 also the client IP and client name, which considerably simplifies mapping an entry to a specific application or process.
SLOWLOG LEN simply returns the current number of stored entries, useful for quick monitoring checks without transferring the full data set. SLOWLOG RESET completely clears the slowlog and is typically used right before a focused test, so only the slow commands that occurred during that test are captured, without noise from older entries.
redis-cli SLOWLOG GET 5
# 1) 1) (integer) 14
# 2) (integer) 1690000123
# 3) (integer) 45123
# 4) 1) "KEYS"
# 2) "session:*"
# 5) "10.0.1.42:51882"
# 6) ""
redis-cli SLOWLOG LEN
# (integer) 27
redis-cli SLOWLOG RESET
# OK
3. Correctly configuring slowlog-log-slower-than
The threshold slowlog-log-slower-than is specified in microseconds and defaults to 10000, that is 10 milliseconds. For most Redis workloads, which typically respond in sub-millisecond time, that is already a fairly generous value: a command taking 10 milliseconds is already a clear warning sign in the Redis context, since simple operations like GET or SET usually fall in the range of ten to a few hundred microseconds.
For more precise diagnostics it is worth temporarily lowering the threshold to 1000 microseconds or even less, to also capture commands in the low millisecond range that, while not individually dramatic, can have a noticeable cumulative effect at high frequency. A value of 0 logs every single command without exception, which is useful for a short, focused diagnostic window but should never stay active permanently in production due to the overhead. The value -1 disables the slowlog entirely.
# redis.conf , tuned for a production workload expecting sub-millisecond commands
slowlog-log-slower-than 1000
slowlog-max-len 512
# Temporary, more aggressive setting for a focused diagnosis window
# CONFIG SET slowlog-log-slower-than 0
# ... reproduce the issue ...
# CONFIG SET slowlog-log-slower-than 1000 # revert afterwards
4. slowlog-max-len and the ring buffer behavior
slowlog-max-len caps the number of entries stored at once, defaulting to 128. Once that limit is reached, every new entry evicts the oldest one, so the slowlog behaves like a classic ring buffer. On a server producing many slow commands within a short time, this effect can mean relevant older entries were already evicted before anyone even read the slowlog.
A higher value for slowlog-max-len, say 512 or 1024, only slightly increases memory usage, since each entry contains only metadata and command arguments, not full data values. For production systems with irregular traffic patterns, a more generous ring buffer is worthwhile so that even a short burst of slow commands leaves enough historical entries for later analysis, instead of being overwritten within a few seconds.
5. Identifying blocking commands: KEYS, SORT, FLUSHALL
KEYS is the classic among blocking commands: it scans the entire keyspace in a single atomic step, blocking all other clients for the whole duration, which with millions of keys can easily reach several seconds. In the slowlog, such a call appears with a strikingly high duration and the argument KEYS followed by the pattern used, immediately identifying it as the prime suspect for a reported latency spike.
SORT without a LIMIT clause on a large list, set, or sorted set is another frequent culprit, as is FLUSHALL and FLUSHDB without the ASYNC option on a large data set, since synchronously freeing every key blocks the event loop for the entire duration. SMEMBERS, HGETALL, or LRANGE on an extremely large data structure can also show up when a data model with unbounded growth has gone unreviewed for a long time.
redis-cli SLOWLOG GET -1 | grep -A 3 "KEYS\|SORT\|FLUSHALL"
# 1) (integer) 22
# 2) (integer) 1690001845
# 3) (integer) 812340
# 4) 1) "KEYS"
# 2) "cache:product:*"
# -- 812ms blocking the entire event loop for a single KEYS scan
# Reproduce and confirm with a temporary, aggressive threshold
redis-cli CONFIG SET slowlog-log-slower-than 0
redis-cli KEYS "cache:product:*"
redis-cli SLOWLOG GET 1
redis-cli CONFIG SET slowlog-log-slower-than 1000
6. Interpreting slowlog entries: timestamp, duration, client
The Unix timestamp of every entry allows correlating it in time with other events like deployments, cron jobs, or backup processes. If the same command recurs at similar times across multiple days, it suggests a periodic job that deserves targeted investigation, rather than a random, one-off event. The duration in microseconds should always be judged relative to the complexity of the command: 5 milliseconds for an HGETALL on a hash with 50000 fields is far less alarming than the same duration for a plain GET.
Client information, IP address and client name, has been available since Redis 4.0 and makes it possible to attribute a problematic command directly to a microservice or an application component, provided the application meaningfully names its Redis connections with CLIENT SETNAME. Without that naming, often only the IP address remains as a clue, which makes attribution harder when several instances of the same application sit behind a load balancer.
| Command in slowlog | Typical cause | Recommended fix | Blocks event loop |
|---|---|---|---|
| KEYS pattern | Full keyspace scan | SCAN with COUNT and MATCH | Yes, completely |
| SORT without LIMIT | Large list/set sorted | SORT with LIMIT or sort client-side | Yes, proportional to size |
| FLUSHALL/FLUSHDB | Synchronous deletion of all keys | FLUSHALL ASYNC | Yes, without ASYNC |
| HGETALL on a large hash | Unbounded data model growth | HSCAN instead of HGETALL | Yes, proportional to size |
| Single GET/SET | Rarely the cause, usually harmless | Usually no fix needed | No, O(1) |
7. From diagnosis to fix: SCAN instead of KEYS and SORT alternatives
The replacement for KEYS is practically always SCAN, which walks the same keyspace incrementally using a cursor, returning only a small, COUNT-controllable number of keys per call. That spreads the load across multiple calls instead of bundling it into a single blocking step, and while it does not guarantee exact consistency across the entire iteration, it is perfectly sufficient for nearly every practical use case such as cache invalidation or maintenance scripts.
For SORT on large data structures, either a LIMIT clause to sort only a subset, or moving the sort to the application side after a simple, unsorted fetch, helps. For FLUSHALL and FLUSHDB, the ASYNC option structurally solves the blocking problem by freeing the actual memory in a background thread while the main thread immediately becomes available for other commands again.
# WRONG: KEYS blocks the entire event loop until the full scan completes
redis-cli KEYS "session:*"
# RIGHT: SCAN iterates incrementally with a cursor, non-blocking
redis-cli --scan --pattern "session:*" --count 100
# WRONG: FLUSHALL blocks until every key is freed synchronously
redis-cli FLUSHALL
# RIGHT: memory reclaim happens in a background thread
redis-cli FLUSHALL ASYNC
# WRONG: HGETALL on a hash with hundreds of thousands of fields
redis-cli HGETALL big:hash
# RIGHT: HSCAN paginates through fields incrementally
redis-cli HSCAN big:hash 0 COUNT 100
8. Integrating the slowlog into your monitoring pipeline
A cron job that periodically queries SLOWLOG GET, distinguishes new entries from already processed ones using the monotonically increasing ID, and writes them into a log or metrics system, turns the slowlog from a reactive into a proactive tool. Since every entry has a unique ID, it is reliable to determine which entries have appeared since the last poll without producing duplicates.
A sensible alerting rule fires as soon as more than a certain number of new slowlog entries appear within a time window, or as soon as a single entry exceeds a duration in the double-digit millisecond range. This automation prevents an entry, already overwritten due to the limited ring buffer, from going unnoticed simply because nobody checked manually in time.
#!/usr/bin/env bash
# slowlog-watch.sh , poll new slowlog entries since the last run, no extra tools
set -euo pipefail
STATE_FILE="/var/tmp/redis-slowlog-last-id"
LAST_ID=$(cat "$STATE_FILE" 2>/dev/null || echo -1)
ENTRIES=$(redis-cli SLOWLOG GET -1)
NEWEST_ID=$(redis-cli SLOWLOG GET 1 | head -1)
# In practice: parse entries, filter id > LAST_ID, alert if duration > 10000us
# or if more than N new entries appeared since the last poll interval
echo "$NEWEST_ID" > "$STATE_FILE"
9. Limits of the slowlog and the latency monitor as a complement
The slowlog only captures pure command execution time inside the Redis engine, not other latency sources such as slow forking for RDB snapshots, AOF rewrite operations, expiry cycles, or OS-level swapping. For those cases, the LATENCY command family, especially LATENCY HISTORY and LATENCY LATEST, provides additional insight into latency event classes that never appear in the slowlog at all, because they are classified as internal operations rather than a single command.
A complete performance diagnosis therefore combines both tools: the slowlog for latency attributable to a specific command, the latency monitor for structural and internal latency sources that cannot be traced back to a single client command. Anyone who relies exclusively on the slowlog systematically overlooks an entire class of performance problems that are just as real, but different in nature.
Mironsoft
Redis performance diagnostics and operational tuning
Finally trace Redis latency spikes to a specific command?
We configure your slowlog for your actual workload, identify blocking commands in your codebase, and guide the migration to non-blocking alternatives like SCAN.
Slowlog configuration
Calibrating thresholds and ring buffer size for your workload
Code audit
Identifying blocking commands like KEYS and SORT in your codebase
Monitoring integration
Automating slowlog evaluation and wiring it into existing alerting
10. Summary
The slowlog is the most direct tool for tracing Redis latency problems back to a specific command, instead of relying on vague guesses. SLOWLOG GET, SLOWLOG LEN, and SLOWLOG RESET form the basic toolkit, while slowlog-log-slower-than and slowlog-max-len determine how sensitive and how extensive logging is. Classic blocking commands include KEYS, unconstrained SORT, and synchronous FLUSHALL, which can almost always be defused with SCAN, LIMIT clauses, and the ASYNC option.
Automated evaluation of the slowlog through a cron job turns it from a reactive into a proactive tool that fires alerts before a user notices the latency spike. Since the slowlog only captures pure command execution time, the latency monitor with LATENCY HISTORY belongs alongside it as a complement, covering structural latency sources like forking or AOF rewrites that never show up in the slowlog at all.
Slowlog for performance diagnostics, the essentials at a glance
Basic commands
SLOWLOG GET, LEN, and RESET return, count, and clear the logged slow commands.
Configuration
Lower slowlog-log-slower-than to 1000 microseconds, raise slowlog-max-len to 512 or higher.
Common culprits
KEYS, unconstrained SORT, and synchronous FLUSHALL block the event loop for the entire execution time.
Complement
LATENCY HISTORY covers structural latency sources the slowlog does not capture.