Fix Redis Error: ERR max number of clients reached

intermediate๐Ÿ”ด Redis2026-03-18| Redis 5.x / 6.x / 7.x on Linux, macOS, Docker

Error Message

(error) ERR max number of clients reached
#redis#connection#maxclients

The Error

Your app tries to connect to Redis and gets this back:

(error) ERR max number of clients reached

Redis hit its configured client limit and is turning away new connections. Nothing gets in until something else disconnects.

Four things typically cause this:

  • A connection leak โ€” your app opens connections but never closes them
  • Multiple app instances each maintaining their own connections instead of sharing a pool
  • The default maxclients limit (10,000) is genuinely too low for your traffic
  • A traffic spike opened thousands of short-lived connections that haven't cleaned up yet

Step 1: Check the Current Client Count

First, confirm the problem and see what you're dealing with:

redis-cli INFO clients

Sample output:

# Clients
connected_clients:10001
cluster_connections:0
maxclients:10000
client_recent_max_input_buffer:20480
client_recent_max_output_buffer:0
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0

connected_clients at 10,001 against a maxclients of 10,000 โ€” that's your confirmation.

Now see what those clients are actually doing:

redis-cli CLIENT LIST

Each line shows the client's IP, last command, and idle time in seconds. Connections sitting idle for 300+ seconds with no recent commands are almost certainly leaks.

Step 2: Kill Idle Connections (Quick Fix)

Need to free up slots right now without restarting Redis? Kill the idle ones.

On Redis 7.4+, one command does it:

# Kill all clients idle for more than 5 minutes
redis-cli CLIENT KILL MAXAGE 300

On older versions, parse CLIENT LIST manually:

redis-cli CLIENT LIST | awk -F'[= ]' '{
  for(i=1;i= 300) print id
  }
}' | xargs -I {} redis-cli CLIENT KILL ID {}

Or target a single connection by its ID from the CLIENT LIST output:

redis-cli CLIENT KILL ID 12345

This buys you breathing room. It won't stop the problem from coming back.

Step 3: Increase maxclients (If the Limit Is Too Low)

Sometimes the limit just isn't high enough for your actual workload. Here's how to raise it.

Option A โ€” Change at runtime (no restart needed)

redis-cli CONFIG SET maxclients 20000

Option B โ€” Change in redis.conf (survives restarts)

Open your Redis config โ€” usually at /etc/redis/redis.conf or /etc/redis.conf:

sudo nano /etc/redis/redis.conf

Find and update:

maxclients 20000

Then reload:

redis-cli CONFIG REWRITE
sudo systemctl reload redis

Option C โ€” Docker / docker-compose

services:
  redis:
    image: redis:7
    command: redis-server --maxclients 20000

OS file descriptor limit: Redis caps maxclients at the OS file descriptor limit minus 32 (reserved for internal use). If you set 20,000 but ulimit -n returns 1024, Redis will silently apply a much lower value. Fix it in /etc/security/limits.conf:

redis soft nofile 65535
redis hard nofile 65535

Step 4: Fix Connection Leaks in Your App

Raising the limit is a band-aid. If connections are leaking, you'll hit the ceiling again โ€” just later. Track down where your app isn't releasing connections and fix it there.

Node.js (ioredis)

The most common mistake: creating a new Redis client per request. Each call opens a new connection that never closes.

// BAD โ€” a fresh connection on every request, none ever closed
app.get('/data', async (req, res) => {
  const client = new Redis();
  const val = await client.get('key');
  res.json(val);
});

// GOOD โ€” one client created once, shared by all requests
const redis = new Redis({ host: 'localhost', port: 6379 });

app.get('/data', async (req, res) => {
  const val = await redis.get('key');
  res.json(val);
});

Python (redis-py)

Use ConnectionPool with an explicit cap so the pool can't grow unbounded:

import redis

pool = redis.ConnectionPool(
    host='localhost',
    port=6379,
    max_connections=50
)
client = redis.Redis(connection_pool=pool)

PHP (Predis / PhpRedis)

PHP-FPM gives every worker its own persistent connection. Do the math before raising maxclients: pm.max_children ร— number_of_servers. For example, 50 workers across 4 app servers means 200 connections minimum โ€” set maxclients above that with headroom to spare.

Step 5: Set a Connection Timeout

Make Redis clean up abandoned connections automatically. Add these two lines to redis.conf:

# Drop clients that go silent for 5 minutes
timeout 300

# Send TCP keepalive probes every 60 seconds
tcp-keepalive 60

Apply without restarting:

redis-cli CONFIG SET timeout 300
redis-cli CONFIG SET tcp-keepalive 60

Verify the Fix

Watch the client count live while your app runs under normal load:

watch -n 2 'redis-cli INFO clients | grep connected_clients'

connected_clients should stay comfortably below maxclients. If it was creeping up before, you'll see it stabilize now.

Confirm the new limit took effect:

redis-cli CONFIG GET maxclients

Quick Reference

  • Immediate relief: Kill idle connections with CLIENT KILL MAXAGE 300 (Redis 7.4+) or CLIENT KILL ID
  • Short-term fix: Raise maxclients with CONFIG SET
  • Permanent fix: Set maxclients in redis.conf, fix connection leaks in app code, raise OS file descriptor limits
  • Prevention: Use a connection pool, set timeout in Redis config, monitor connected_clients continuously โ€” Prometheus + redis_exporter is the standard setup for this

Related Error Notes