# Redis Max Clients Reached

Error Message

bash
ERR max number of clients reached

Or:

bash
Redis::ConnectionError: max number of clients reached

Or:

bash
Could not connect to Redis: max number of clients reached

Root Causes

  1. 1.maxclients limit too low - Default or configured limit insufficient
  2. 2.Connection leaks - Clients not closing connections properly
  3. 3.Connection pooling issues - Pool creating too many connections
  4. 4.Idle connections not closing - Connections staying open unnecessarily
  5. 5.High traffic spikes - Temporary surge exceeding capacity
  6. 6.Multiple application instances - Too many clients from many sources

Diagnosis Steps

Step 1: Check Current Client Count

```bash # Check connected clients redis-cli CLIENT LIST | wc -l

# Or use INFO redis-cli INFO clients

# Key fields: # connected_clients: current count # client_recent_max_input_buffer: buffer sizes # blocked_clients: clients waiting on blocking commands ```

Step 2: Check Max Clients Configuration

```bash # Check maxclients setting redis-cli CONFIG GET maxclients

# Default is typically 10000 ```

Step 3: Identify Client Sources

```bash # List all clients with details redis-cli CLIENT LIST

# Output fields: # id=<id> addr=<ip:port> fd=<file descriptor> name=<client_name> age=<seconds_connected> idle=<seconds_idle> ...

# Count by source IP redis-cli CLIENT LIST | awk '{print $2}' | cut -d= -f2 | cut -d: -f1 | sort | uniq -c | sort -rn ```

Step 4: Find Idle Connections

```bash # Find clients idle for more than 60 seconds redis-cli CLIENT LIST | awk -F'[ =]' '{for(i=1;i<=NF;i++) if($i=="idle") print $(i+1)}' | awk '$1 > 60 {print}'

# Or more detailed redis-cli CLIENT LIST | while read line; do idle=$(echo "$line" | grep -oP 'idle=\K[0-9]+') addr=$(echo "$line" | grep -oP 'addr=\K[^ ]+') if [ "$idle" -gt 60 ]; then echo "Idle client: $addr (idle: $idle seconds)" fi done ```

Step 5: Check for Name/Tagged Clients

```bash # Find clients with names (helpful for debugging) redis-cli CLIENT LIST | grep "name="

# Client names help identify source application ```

Solutions

Solution 1: Increase maxclients

```bash # Increase limit dynamically redis-cli CONFIG SET maxclients 20000

# Or in redis.conf # /etc/redis/redis.conf maxclients 20000 ```

Note: Each connection uses memory (approximately 8KB + buffers). Ensure you have enough memory.

Solution 2: Kill Idle Connections

```bash # Find and kill idle clients redis-cli CLIENT LIST | while read line; do idle=$(echo "$line" | grep -oP 'idle=\K[0-9]+') id=$(echo "$line" | grep -oP 'id=\K[0-9]+') if [ "$idle" -gt 300 ]; then # 5 minutes idle redis-cli CLIENT KILL ID $id fi done

# Or kill all idle clients over threshold redis-cli CLIENT KILL TYPE normal ```

Solution 3: Configure Timeout for Idle Clients

```bash # Set timeout (seconds) for idle connections redis-cli CONFIG SET timeout 300 # 5 minutes

# In redis.conf timeout 300

# Note: 0 means no timeout (default) ```

Solution 4: Fix Application Connection Handling

Node.js with ioredis:

```javascript const Redis = require('ioredis');

// Use connection pool correctly const redis = new Redis({ host: 'localhost', port: 6379, maxRetriesPerRequest: 3, enableReadyCheck: true, // Connection is reused automatically });

// Set client name for debugging redis.client('SETNAME', 'my-app-worker-1');

// Gracefully close on shutdown process.on('SIGTERM', async () => { await redis.quit(); process.exit(0); }); ```

Python with redis-py:

```python import redis from redis.connection import ConnectionPool

# Use connection pool pool = ConnectionPool( host='localhost', port=6379, max_connections=10 # Limit connections in pool )

r = redis.Redis(connection_pool=pool)

# Set client name r.client_setname('my-app-service')

# Close properly def cleanup(): pool.disconnect() ```

PHP with Predis:

```php <?php require 'vendor/autoload.php';

// Use connection pool $client = new Predis\Client([ 'scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => 6379, ], [ 'connections' => Predis\Connection\PhpiredisSocketFactory::class ]);

// Set client name $client->client('SETNAME', 'my-php-app');

// Disconnect properly $client->disconnect(); ```

Solution 5: Implement Connection Pooling

```javascript // Node.js - create shared pool const { createPool } = require('generic-pool');

const redisPool = createPool({ create: async () => { const redis = new Redis({ host: 'localhost', port: 6379 }); await redis.client('SETNAME', 'pool-client'); return redis; }, destroy: async (redis) => { await redis.quit(); } }, { max: 10, // Maximum connections min: 2, // Minimum connections idleTimeoutMillis: 30000, acquireTimeoutMillis: 5000 });

// Use pool async function getFromCache(key) { const redis = await redisPool.acquire(); try { return await redis.get(key); } finally { await redisPool.release(redis); } } ```

Solution 6: Configure TCP Settings

```bash # Check current TCP settings sysctl net.core.somaxconn sysctl net.ipv4.tcp_max_syn_backlog

# Increase backlog sudo sysctl -w net.core.somaxconn=65535 sudo sysctl -w net.ipv4.tcp_max_syn_backlog=65535

# In redis.conf tcp-backlog 511 # Should be <= somaxconn ```

Solution 7: Monitor Client Connections

```bash #!/bin/bash # monitor_clients.sh

MAX_THRESHOLD=80

CURRENT=$(redis-cli INFO clients | grep connected_clients | cut -d: -f2 | tr -d '\r') MAX=$(redis-cli CONFIG GET maxclients | tail -1)

PERCENT=$((CURRENT * 100 / MAX))

if [ $PERCENT -gt $MAX_THRESHOLD ]; then echo "WARNING: Client connections at ${PERCENT}% (${CURRENT}/${MAX})" echo "Top client sources:" redis-cli CLIENT LIST | awk '{print $2}' | cut -d= -f2 | cut -d: -f1 | sort | uniq -c | sort -rn | head -5 exit 1 fi

echo "OK: Client connections at ${PERCENT}% (${CURRENT}/${MAX})" ```

Solution 8: Use Redis Sentinel for Scaling

For high connection requirements, use multiple Redis instances:

```bash # Set up Redis Sentinel for read scaling # Multiple replicas can handle read connections

# Master handles writes # Replicas handle reads # Distribute connections across replicas ```

Configuration for Production

```ini # /etc/redis/redis.conf

# Connection limits maxclients 10000

# Timeout for idle connections timeout 300

# TCP backlog tcp-backlog 511

# TCP keepalive tcp-keepalive 300

# Protected mode (use authentication) protected-mode yes requirepass your_secure_password ```

Application Best Practices

1. Always Set Client Names

javascript
// Set name after connection
redis.client('SETNAME', `app-${process.env.HOSTNAME}-${process.pid}`);

2. Use Single Connection Per Process

```javascript // Don't create multiple Redis instances // Use singleton pattern

let redisInstance = null;

function getRedis() { if (!redisInstance) { redisInstance = new Redis({ host: 'localhost', port: 6379 }); } return redisInstance; } ```

3. Handle Shutdown Properly

```javascript // Always close connections on shutdown async function shutdown() { if (redisInstance) { await redisInstance.quit(); } }

process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown); ```

4. Use Connection Pooling for Multi-process Apps

```python # For web servers with many workers # Use shared connection pool with limits

pool = ConnectionPool( host='redis-host', port=6379, max_connections=20 # Per worker pool ) ```

Monitoring Script

```bash #!/bin/bash # client_monitor.sh

while true; do CURRENT=$(redis-cli INFO clients | grep connected_clients | cut -d: -f2 | tr -d '\r') MAX=$(redis-cli CONFIG GET maxclients | tail -1) IDLE=$(redis-cli CLIENT LIST | awk -F'[ =]' '{for(i=1;i<=NF;i++) if($i=="idle") print $(i+1)}' | awk '$1 > 60' | wc -l)

echo "$(date): Connected: $CURRENT/$MAX, Idle (>60s): $IDLE"

if [ "$CURRENT" -gt 80 ]; then # Alert if approaching limit echo "HIGH CONNECTION COUNT" fi

sleep 10 done ```

Prevention Checklist

  • [ ] Set appropriate maxclients limit
  • [ ] Implement connection pooling
  • [ ] Set timeout for idle connections
  • [ ] Always close connections on shutdown
  • [ ] Set client names for identification
  • [ ] Monitor connection count
  • [ ] Use single connection per process where possible
  • [ ] Distribute read load across replicas
  • [Redis Connection Refused](./fix-redis-connection-refused)
  • [Redis Out of Memory](./fix-redis-out-of-memory)