Module P-10·18 min read

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.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

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.

typescript

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

typescript

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).

typescript

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.

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.