Using the Slowlog for Targeted Performance Diagnostics
AI generated
SET
TTL
Redis · Slowlog · Performance · Diagnostics
The Slowlog for Performance Diagnostics
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.

13 min read SLOWLOG GET · slowlog-log-slower-than Redis 6.x · 7.x · performance diagnostics

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.

11. FAQ: the slowlog for performance diagnostics

1What does the slowlog measure?
Only pure command execution time inside the Redis engine, not network latency or round-trip time.
2How do I read it?
SLOWLOG GET returns entries with timestamp, duration, arguments, and since Redis 4.0 client information.
3Default value of slowlog-log-slower-than?
10000 microseconds. Temporarily lower to 1000 or less for more precise diagnostics.
4What when slowlog-max-len is reached?
Ring buffer behavior: new entries evict the oldest. Relevant entries can be overwritten quickly.
5Why is KEYS problematic?
Blocks the event loop for the entire scan duration, potentially several seconds with millions of keys.
6Alternative to KEYS?
SCAN walks the keyspace incrementally with a cursor and spreads load across multiple calls.
7Fixing FLUSHALL blocking?
FLUSHALL ASYNC frees memory in the background, keeping the main thread immediately available.
8Can I automate evaluation?
Yes, a cron job with SLOWLOG GET, detecting new entries by ID, alerting past a threshold.
9Does it capture every latency issue?
No, structural sources like forking or swapping require LATENCY HISTORY as a complement.
10Keep slowlog-log-slower-than at 0 forever?
No, it creates noticeable overhead. Only suitable for short, focused diagnostic windows.