Redis 'Connection Refused': Complete Troubleshooting Guide (Connection Pool, Timeout, Too Many Connections)
Fix Redis connection refused, pool exhausted, timeout, and too many connections errors with exact diagnostic commands and configuration fixes.
- Root cause 1: Redis process is not running or bound to wrong interface — verify with `redis-cli ping` and check `bind` directive in redis.conf
- Root cause 2: Connection pool exhausted or maxclients limit hit — tune pool size, use connection multiplexing, or raise `maxclients` in redis.conf
- Root cause 3: Firewall or network ACL blocking port 6379 — check with `telnet <host> 6379` or `nc -zv <host> 6379`
- Root cause 4: Authentication failure — Redis 6+ ACLs or `requirepass` directive rejecting credentials
- Root cause 5: Slow commands blocking the event loop — identify with SLOWLOG GET and avoid KEYS, SMEMBERS on large sets
- Quick fix summary: Check process → verify bind/port → test network → audit maxclients/pool config → review AUTH → inspect SLOWLOG
| Method | When to Use | Time to Apply | Risk |
|---|---|---|---|
| Restart Redis service | Process crashed or not started | < 1 min | Low — brief downtime |
| Update bind directive in redis.conf | Redis listening on wrong interface (127.0.0.1 only) | 2–5 min + reload | Medium — exposes Redis if misconfigured |
| Raise maxclients in redis.conf | MISCONF error or too many connections | 2 min + CONFIG SET | Low — monitor memory impact |
| Tune connection pool in client library | Pool exhausted errors in application logs | 10–30 min dev time | Low — requires deploy |
| Add requirepass / fix ACL credentials | NOAUTH or WRONGPASS errors | 5 min + client update | Medium — breaks clients without updated creds |
| Identify and fix slow commands (SLOWLOG) | Latency spikes, timeouts under load | 30–60 min analysis | Low — code change required |
| Promote replica or fix replication lag | Stale reads, replica lag > threshold | 5–20 min | High — involves failover |
| Implement pipelining / Lua scripts | High command-per-second overhead | Hours of refactoring | Low — improves throughput |
Understanding Redis Connection Errors
Redis is a single-threaded, event-loop-driven server. Almost every production incident traces back to one of six failure modes: the process isn't running, the network path is blocked, the server hit its connection ceiling, authentication is misconfigured, a slow command is monopolizing the event loop, or replication has fallen behind. Each mode produces a distinctive error message.
Exact Error Messages You Will See
Error: connect ECONNREFUSED 127.0.0.1:6379 # Node.js / ioredis
redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused. # Python redis-py
ERR max number of clients reached # Redis server log
NOAUTH Authentication required. # Missing password
WRONGPASS invalid username-password pair # Wrong credentials (Redis 6+)
READONLY You can't write against a read only replica # Writing to replica
BUSY Redis is busy running a script # Long-running Lua
Step 1: Confirm Redis Is Running
The most common cause of Connection refused is that the Redis process stopped — OOM killer, systemd restart policy, or a failed RDB/AOF flush.
# Check process status
systemctl status redis-server # Debian/Ubuntu
systemctl status redis # RHEL/CentOS
# Quick connectivity test
redis-cli -h 127.0.0.1 -p 6379 ping
# Expected: PONG
# Got: Could not connect to Redis at 127.0.0.1:6379: Connection refused
# Confirm socket / port is open
ss -tlnp | grep 6379
# If empty: Redis is not listening
If the service is stopped, check /var/log/redis/redis-server.log before restarting:
tail -100 /var/log/redis/redis-server.log | grep -E 'WARN|ERR|FATAL'
Common log entries that explain a crash:
# Can't save in background: fork: Cannot allocate memory— OOM, enablevm.overcommit_memory = 1# Failed opening .rdb for saving: Permission denied— data directory ownership issue# Creating Server TCP listening socket 0.0.0.0:6379: bind: Address already in use— port conflict
Step 2: Verify Bind Address and Network Path
By default, Redis 3.2+ binds to 127.0.0.1 only. Remote connections will be refused even if the process is running.
# Check what address Redis is bound to
grep '^bind' /etc/redis/redis.conf
# Default: bind 127.0.0.1 -::1
# Test from a remote host
nc -zv <redis-host> 6379
telnet <redis-host> 6379
# Check firewall (iptables)
iptables -L INPUT -n | grep 6379
# Check firewall (nftables / ufw)
ufw status | grep 6379
nft list ruleset | grep 6379
To allow remote connections safely:
# In redis.conf — bind to specific interface, NOT 0.0.0.0 without a firewall
bind 127.0.0.1 10.0.1.5
# Apply without restart (Redis 6.2+)
redis-cli CONFIG SET bind-source-addr "" # not for bind directive — requires restart
sudo systemctl reload redis-server
Always pair a non-localhost bind with a firewall rule and requirepass / ACLs.
Step 3: Diagnose and Fix Connection Limits
Too Many Connections / Pool Exhausted
ERR max number of clients reached
Redis has a hard maxclients limit (default: 10000). Connection pools in your application layer are a separate concern.
# Current connection count
redis-cli INFO clients | grep connected_clients
# connected_clients:9987 <-- approaching limit
# See which clients are connected
redis-cli CLIENT LIST
# Check maxclients setting
redis-cli CONFIG GET maxclients
# Raise the limit at runtime (no restart needed)
redis-cli CONFIG SET maxclients 20000
# Persist to redis.conf
echo 'maxclients 20000' >> /etc/redis/redis.conf
# Check OS file descriptor limit (must be > maxclients)
ulimit -n
# If too low:
ulimit -n 65535
# Persist: add to /etc/security/limits.conf
# redis soft nofile 65535
# redis hard nofile 65535
Application-Level Pool Exhaustion
If connected_clients is well below maxclients but your app throws pool errors, the pool is undersized or connections are leaking.
Python (redis-py):
import redis
pool = redis.ConnectionPool(
host='localhost',
port=6379,
max_connections=50, # tune to your concurrency
socket_timeout=5,
socket_connect_timeout=2,
retry_on_timeout=True
)
client = redis.Redis(connection_pool=pool)
Node.js (ioredis):
const Redis = require('ioredis');
const client = new Redis({
host: 'localhost',
port: 6379,
maxRetriesPerRequest: 3,
connectTimeout: 2000,
commandTimeout: 5000,
lazyConnect: false,
family: 4
});
Step 4: Diagnose Timeouts and Slow Queries
A redis timeout error means a command took longer than the client's configured timeout. The usual culprit is a slow command blocking the event loop.
# Enable slow log (commands taking > 10ms)
redis-cli CONFIG SET slowlog-log-slower-than 10000 # microseconds
redis-cli CONFIG SET slowlog-max-len 256
# Retrieve the slow log
redis-cli SLOWLOG GET 25
# Output: ID, timestamp, execution time (µs), command + args
# Check instantaneous latency
redis-cli --latency -h localhost -p 6379
# Intrinsic latency (baseline OS noise)
redis-cli --intrinsic-latency 30
# Monitor live commands (use sparingly in prod — impacts performance)
redis-cli MONITOR | head -50
Dangerous commands to find and replace:
| Dangerous | O(n) Risk | Safe Alternative |
|---|---|---|
| KEYS * | Blocks all clients | SCAN cursor MATCH * COUNT 100 |
| SMEMBERS (large set) | Returns all members | SSCAN |
| HGETALL (huge hash) | Returns all fields | HSCAN |
| SORT (large list) | CPU intensive | Pre-sorted structures |
| FLUSHDB / FLUSHALL | Blocks for seconds | FLUSHDB ASYNC |
# Find all KEYS calls in application code
grep -r 'KEYS \*' ./src --include='*.py' --include='*.js' --include='*.go'
# Use SCAN instead in a script
redis-cli --scan --pattern 'session:*' | wc -l
Step 5: Fix Authentication Errors
Redis 6 introduced ACL-based multi-user authentication. The old requirepass still works but is treated as setting the password for the default user.
# Test authentication
redis-cli -h localhost -p 6379 -a 'yourpassword' ping
# If using ACLs (Redis 6+)
redis-cli ACL LIST
redis-cli ACL WHOAMI
# Add a new user with specific permissions
redis-cli ACL SETUSER appuser on >strongpassword ~* &* +@all
# Persist ACLs to file (recommended over requirepass for Redis 6+)
# In redis.conf:
# aclfile /etc/redis/users.acl
redis-cli ACL SAVE
# Test new user
redis-cli -u redis://appuser:strongpassword@localhost:6379 ping
Step 6: Diagnose and Fix Replication Lag
Replication lag causes stale reads on replicas and can manifest as data loss during failover.
# On the primary
redis-cli INFO replication
# Look for:
# role:master
# connected_slaves:2
# slave0:ip=10.0.1.10,port=6379,state=online,offset=12345678,lag=0
# repl_backlog_size:1048576
# On the replica
redis-cli INFO replication
# Look for:
# role:slave
# master_link_status:up
# master_last_io_seconds_ago:1
# master_sync_in_progress:0
# slave_repl_offset:12345670
# slave_priority:100
# slave_read_only:1
# Calculate lag in bytes
redis-cli -h primary INFO replication | grep master_repl_offset
redis-cli -h replica INFO replication | grep slave_repl_offset
# Increase replication backlog for high-throughput primaries
redis-cli CONFIG SET repl-backlog-size 67108864 # 64MB
# Increase timeout before replica marks primary as down
redis-cli CONFIG SET repl-timeout 120
If replica shows master_link_status:down:
# Check replica log
tail -50 /var/log/redis/redis-server.log | grep -i repl
# MASTER <-> REPLICA sync started
# Error condition on socket for SYNC: Connection timed out
# Reconnecting to MASTER <primary-ip>:6379 after failure
# Force resync from replica
redis-cli REPLICAOF NO ONE # demote to standalone
redis-cli REPLICAOF <primary-ip> 6379 # re-attach
Step 7: Validate Redis Deadlock / Blocked Clients
# Check for blocked clients (waiting on BLPOP, BRPOP, WAIT)
redis-cli INFO clients | grep blocked_clients
# See which commands are blocking
redis-cli CLIENT LIST | grep flags=b
# Kill a specific blocked client
redis-cli CLIENT KILL ID <client-id>
# Check for Lua script timeouts (BUSY state)
redis-cli DEBUG SLEEP 0 # no-op to test responsiveness
# If this hangs: a Lua script is running
redis-cli SCRIPT KILL # kills the running script (if not in write)
Production Checklist
- Enable
hz 20in redis.conf for more frequent background task cycles under high load - Set
tcp-keepalive 300to detect dead connections - Configure
timeout 0carefully — idle client connections consume memory - Use
maxmemory-policy allkeys-lruto prevent OOM on cache workloads - Deploy Redis with Sentinel or Cluster for HA; never rely on a single instance in production
- Always set
save ""to disable RDB if using Redis purely as a cache (reduces fork latency)
Frequently Asked Questions
#!/usr/bin/env bash
# Redis Connection Diagnostic Script
# Usage: bash redis-diag.sh [host] [port] [password]
HOST=${1:-127.0.0.1}
PORT=${2:-6379}
PASS=${3:-""}
CLI="redis-cli -h $HOST -p $PORT"
[ -n "$PASS" ] && CLI="$CLI -a $PASS"
echo "=== Redis Diagnostic Report ==="
echo "Target: $HOST:$PORT"
echo "Date: $(date -u)"
echo ""
echo "--- 1. Connectivity ---"
if nc -z -w3 "$HOST" "$PORT" 2>/dev/null; then
echo "TCP port $PORT is OPEN"
else
echo "ERROR: Cannot reach $HOST:$PORT - check firewall/bind config"
exit 1
fi
echo ""
echo "--- 2. Ping ---"
RESP=$($CLI PING 2>&1)
if [ "$RESP" = "PONG" ]; then
echo "PONG received - Redis is responding"
else
echo "ERROR: $RESP"
fi
echo ""
echo "--- 3. Client Connections ---"
$CLI INFO clients 2>&1 | grep -E 'connected_clients|blocked_clients|maxclients'
$CLI CONFIG GET maxclients 2>&1 | tail -1 | xargs echo "maxclients config:"
echo ""
echo "--- 4. Memory ---"
$CLI INFO memory 2>&1 | grep -E 'used_memory_human|maxmemory_human|mem_fragmentation_ratio'
echo ""
echo "--- 5. Replication ---"
$CLI INFO replication 2>&1
echo ""
echo "--- 6. Slowlog (last 10 entries) ---"
$CLI SLOWLOG RESET 2>/dev/null
sleep 5 # brief window to capture slow commands
$CLI SLOWLOG GET 10 2>&1
echo ""
echo "--- 7. Command Stats (top 10 by calls) ---"
$CLI INFO commandstats 2>&1 | grep -v '^#' | sort -t= -k2 -t, -k1 -rn | head -10
echo ""
echo "--- 8. Latency Histogram ---"
$CLI LATENCY HISTORY event 2>&1 || echo "(latency monitoring not active -- run: CONFIG SET latency-monitor-threshold 1)"
echo ""
echo "--- 9. OS File Descriptor Limit ---"
echo "Current ulimit -n: $(ulimit -n)"
REDIS_PID=$(pgrep -x redis-server | head -1)
if [ -n "$REDIS_PID" ]; then
echo "Redis PID $REDIS_PID open FDs: $(ls /proc/$REDIS_PID/fd 2>/dev/null | wc -l)"
fi
echo ""
echo "--- 10. Configuration Audit ---"
for KEY in bind maxclients timeout tcp-keepalive maxmemory maxmemory-policy appendonly hz repl-backlog-size; do
VAL=$($CLI CONFIG GET "$KEY" 2>/dev/null | tail -1)
printf "%-25s %s\n" "$KEY:" "$VAL"
done
echo ""
echo "=== Diagnostic Complete ==="Error Medic Editorial
Error Medic Editorial is a team of senior DevOps engineers, SREs, and infrastructure architects with experience operating Redis at scale across cloud and on-premises environments. Our guides are written from real incident post-mortems and validated against official documentation and community best practices.
Sources
- https://redis.io/docs/management/troubleshooting/
- https://redis.io/docs/management/config/
- https://redis.io/commands/slowlog/
- https://redis.io/docs/management/replication/
- https://redis.io/docs/management/security/acl/
- https://github.com/redis/redis/issues/2332
- https://stackoverflow.com/questions/19581059/misconf-redis-is-configured-to-save-rdb-snapshots