go-redis/redis · error
redis: connection pool exhausted
Error message
redis: connection pool exhausted
What it means
pool.ErrPoolExhausted is returned when the number of active connections has reached MaxActiveConns and a new connection is requested without waiting (pool.go:60-62, thrown at pool.go:627/649). Unlike ErrPoolTimeout this fails immediately (no queue wait) on the NewConn path when MaxActiveConns is bounded.
Source
Thrown at internal/pool/pool.go:62
// These represent the logical state of a connection from a metrics perspective,
// not the internal state machine state (ConnState).
const (
// MetricStateIdle indicates the connection is idle in the pool,
// ready to be acquired.
MetricStateIdle = "idle"
// MetricStateUsed indicates the connection is currently being used
// by a client operation.
MetricStateUsed = "used"
)
var (
// ErrClosed performs any operation on the closed client will return this error.
ErrClosed = errors.New("redis: client is closed")
// ErrPoolExhausted is returned from a pool connection method
// when the maximum number of database connections in the pool has been reached.
ErrPoolExhausted = errors.New("redis: connection pool exhausted")
// ErrPoolTimeout timed out waiting to get a connection from the connection pool.
ErrPoolTimeout = errors.New("redis: connection pool timeout")
// ErrConnUnusableTimeout is returned when a connection is not usable and we timed out trying to mark it as unusable.
ErrConnUnusableTimeout = errors.New("redis: timed out trying to mark connection as unusable")
// errHookRequestedRemoval is returned when a hook requests connection removal.
errHookRequestedRemoval = errors.New("hook requested removal")
// errConnNotPooled is returned when trying to return a non-pooled connection to the pool.
errConnNotPooled = errors.New("connection not pooled")
// errConnEvictedIdle is passed to OnRemove hooks when a pooled connection is evicted on
// Put because the idle pool is already at MaxIdleConns.
errConnEvictedIdle = errors.New("connection evicted: idle pool at capacity")
// metricCallbackMu protects all global metric callback functions for thread-safe access.View on GitHub (pinned to 36d97525cd)
Solutions
- Increase Options.PoolSize (and MinIdleConns) to match peak concurrency.
- Eliminate connection leaks — ensure transactions/pipelines complete and return conns.
- Reduce concurrency or shorten long-running blocking commands.
- Set MaxActiveConns appropriately or leave 0 to tie it to PoolSize.
Example fix
// before
opt := &redis.Options{Addr: addr} // small default pool
// after
opt := &redis.Options{
Addr: addr,
PoolSize: 64,
MinIdleConns: 16,
} Defensive patterns
Strategy: validation
Validate before calling
// Size the pool for peak concurrency before load.
opts := &redis.Options{Addr: addr, PoolSize: runtime.GOMAXPROCS(0) * 16, MinIdleConns: 16} Try / catch
err := client.Get(ctx, key).Err()
if errors.Is(err, redis.ErrPoolExhausted) {
// back off briefly and retry; or report load shedding
time.Sleep(backoff)
} Prevention
- Set PoolSize to match peak concurrency; raise MinIdleConns.
- Audit for connection leaks (unclosed transactions/pipelines).
- Limit concurrency at the application layer to pool capacity.
When it happens
Trigger: More concurrent operations than MaxActiveConns, or a spike in demand while existing connections are checked out; also triggered when PoolSize/MaxActiveConns is misconfigured for the workload.
Common situations: Default PoolSize (10*runtime.NumCPU) too small for high concurrency, long-running commands (BLPOP, long scripts) hoarding connections, or connection leaks (conn not Put back).
Related errors
- redis: connection pool timeout
- redis: connection not available
- redis: connection not available for write operation
- redis: client is closed
- redis: timed out trying to mark connection as unusable
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/0c7f0d18c4c8ebcd.json.
Report an issue: GitHub.