TCP connection overhead, ioredis connection pool sizing, reconnection strategies with exponential backoff, command timeout configuration, lazy connect vs eager connect, and health check patterns for production clients.
P-10 — Connection Pooling and Client Configuration
Who this module is for: You create a Redis client with
new Redis()and call commands on it. It works. But under production load you see connection refused errors, command timeouts, or Redis reporting hundreds of connected clients. This module covers how Redis connections work at the TCP level, how ioredis manages connections, and how to configure your client for production reliability.
The Cost of a TCP Connection
Every Redis client maintains at least one persistent TCP connection to the Redis server. Establishing a TCP connection requires a three-way handshake (SYN → SYN-ACK → ACK) plus any TLS handshake — roughly 1–3 RTTs before the first command can be sent.
Redis itself can handle tens of thousands of concurrent connections, but each connection consumes:
- ~20KB of kernel socket buffer (send + receive)
- A slot in Redis's client list (memory for the client struct, output buffer)
- A file descriptor on both the client and server side
For a Node.js application, one Redis client holds one persistent TCP connection that is multiplexed — all commands share the connection via the RESP protocol. This is different from PostgreSQL's connection model where each database session is a separate stateful connection requiring explicit pooling.
ioredis Connection Model
ioredis maintains a single persistent TCP connection per Redis instance. Commands are sent over this connection and responses are parsed in order. Pipelining (auto-pipelining) batches commands issued in the same event loop tick.
When One Connection is Not Enough
A single connection becomes a bottleneck when:
- You have many concurrent
await redis.command()calls that cannot be batched - Some commands block the connection (BLPOP, SUBSCRIBE)
- You need Pub/Sub (subscriber mode) alongside normal commands
For these cases, create multiple Redis instances or use a cluster/sentinel client.
Key Configuration Options
connectTimeout vs commandTimeout
connectTimeout— how long to wait for the initial TCP + auth handshake. If Redis is briefly unavailable at startup, this controls how long you wait before failing.commandTimeout— how long to wait for a command response after sending it. This is the most important setting to prevent hung requests. Without it, a command can wait forever if the connection drops mid-flight.
Always set commandTimeout. A reasonable value is 2–5× your P99 Redis latency. For a Redis instance with P99 < 5ms, set commandTimeout: 500 (500ms). This allows for occasional latency spikes without hanging your application.
retryStrategy
The retry strategy function receives the number of previous retry attempts and returns the milliseconds to wait before the next attempt (or null to stop retrying).
maxRetriesPerRequest: 3 — limits how many times a command is retried on connection error. The default of 20 means a command issued during a Redis outage can block for up to 20 reconnection cycles before failing. For most applications, 2–3 retries is more appropriate.
Connection Events
Always listen for error events. An unhandled error event on an EventEmitter crashes the Node.js process. Even if you just log and continue, register the handler.
Multiple Connections for Specific Use Cases
Pub/Sub Requires a Dedicated Connection
A subscribed connection cannot issue non-Pub/Sub commands. Always use a separate Redis instance for subscribers.
Blocking Commands
BLPOP, BRPOP, BLMOVE, XREAD BLOCK — these block the connection until data is available. If you use them on your main Redis connection, no other commands can be sent until the block resolves.
Health Checks and Circuit Breaking
In production, Redis may become temporarily unavailable — brief network interruptions, rolling restarts, failovers. Your application should degrade gracefully rather than hanging.
Periodic Health Check
Graceful Degradation
Design cache reads to degrade gracefully when Redis is unavailable:
Cache writes should also be non-blocking on failure:
Sentinel and Cluster Clients
For production deployments with Sentinel or Cluster, ioredis provides dedicated client classes:
Sentinel Client
The Sentinel client queries the sentinels to discover the current primary address and reconnects automatically on failover.
Cluster Client
The Cluster client handles MOVED and ASK redirections automatically.
Monitoring Connections
blocked_clients > 0 is normal if you use blocking commands. A large number that is growing suggests workers are blocking and not consuming from queues.
connected_clients approaching maxclients is a warning. Increase maxclients in redis.conf or identify clients that are not disconnecting (connection leaks).
Summary
- Redis uses persistent TCP connections — one connection per
Redisinstance, multiplexed via RESP - Always set
commandTimeout— prevents commands from hanging indefinitely on connection issues - Set
maxRetriesPerRequest: 2-3— the default of 20 holds commands too long during outages retryStrategycontrols reconnection backoff — use exponential backoff with jitter, cap retries- Pub/Sub and blocking commands (
BLPOP) require dedicatedRedisinstances - Always listen for
errorevents — unhandlederroron an EventEmitter crashes Node.js - For Sentinel: use the
sentinelsoption; for Cluster: useioredis.Cluster - Monitor
connected_clientsandblocked_clientsviaINFO clients - Design cache reads to degrade gracefully — catch Redis errors and fall back to the database
Next: P-11 — Monitoring and Observability — the INFO command section by section, SLOWLOG analysis, LATENCY HISTORY, and the 10 metrics every Redis dashboard must include.
A Node.js application uses ioredis with default configuration settings. During a minor network partition, the application loses connectivity to Redis for 10 seconds. How does ioredis handle the commands issued by the application during this 10-second window?
An engineer notices that their application's primary Redis connection is occasionally unresponsive to standard GET and SET commands, yet INFO clients shows the connection is active. The application uses a single ioredis instance for all operations. Which of the following operations is most likely causing the primary connection to hang?
What is the primary operational difference between configuring connectTimeout and commandTimeout in a Redis client?
Test your knowledge with more question sets
Sign in to access a wider variety of questions and get notified when new practice sets are added to this module.
Sign in & RegisterDiscussion
0Join the discussion