Skip to content

Use Client Pool

The Client Pool manages a set of reusable GLIDE client instances that can be borrowed and returned on demand. Use it when your application needs high concurrency, runs blocking commands like BLPOP, BRPOP, or XREAD BLOCK that tie up a connection, or requires connection isolation between independent workflows.

The pool is configured with a PoolConfig object. All parameters are optional and have sensible defaults.

ParameterTypeDefaultDescription
max_size / maxSize / MaxSizeint10Maximum number of client instances in the pool
min_idle / minIdle / MinIdleint1Number of clients to pre-warm at creation
idle_timeout_ms / idleTimeout / IdleTimeoutduration5 min (Node.js: 30 sec)How long an idle client stays in the pool before eviction
request_timeout_ms / requestTimeout / RequestTimeoutduration5 secBase timeout for state reset (DISCARD, SELECT) when returning a client; the reset is abandoned and the connection discarded after 2× this value. (Node.js has no pool field; it uses the client config’s requestTimeout.)
acquire_timeout_s / acquireTimeoutS / AcquireTimeoutduration5 secHow long to wait for a client when the pool is exhausted
abandon_timeout_ms / abandonTimeoutMs / AbandonTimeoutduration5 min (300000 ms)Maximum inactivity time for a borrowed client before the pool reclaims it. The timer resets on every command sent. The abandon monitor skips clients executing blocking commands. Set to 0 to disable (in Go, set to a negative value to disable; 0 means use default).
from glide import GlideClientConfiguration, NodeAddress
from glide import AsyncClientPool, PoolConfig
pool_config = PoolConfig(
max_size=10,
min_idle=2,
acquire_timeout_s=5.0,
)
client_config = GlideClientConfiguration([NodeAddress("localhost", 6379)])
pool = await AsyncClientPool.create(client_config, pool_config)

Acquire a client from the pool before use, and always release it when done. Use context managers or try/finally blocks to guarantee the client is returned even if an error occurs.

async with pool.borrow() as client:
await client.set("key", "value")
result = await client.get("key")

Check the current state of the pool to monitor utilization and diagnose capacity issues.

metrics = pool.metrics()
print(f"Idle: {metrics['idle']}, Active: {metrics['active']}, Total: {metrics['total']}")

The pool runs a background monitor that reclaims borrowed clients when they have been inactive beyond a configurable timeout. This prevents connection leaks when application code forgets to return a client.

How it works:

  • The monitor scans at half the timeout interval (e.g., every 2.5 minutes with the default 5-minute timeout).
  • A borrowed client is reclaimed if no command has been sent to it within the threshold.
  • The inactivity timer resets on every command sent to the borrowed client.
  • Blocking commands (BLPOP, BRPOP, XREAD BLOCK, etc.) are automatically detected and excluded from reclaim.
  • When a client is reclaimed, the connection is discarded and a fresh one is created on the next acquire().
from glide import PoolConfig
# Set abandon timeout to 1 minute
pool_config = PoolConfig(abandon_timeout_ms=60000)
# Disable abandon detection
pool_config = PoolConfig(abandon_timeout_ms=0)

When your application shuts down, close the pool to release all connections.

pool.close()
# Or use as an async context manager:
async with await AsyncClientPool.create(config, pool_config) as pool:
async with pool.borrow() as client:
await client.set("key", "value")

The following apply to the preview release.

These are intentional constraints for this release. Design your application around them.

  • No Pub/Sub subscriptions: Clients with active subscriptions are rejected at pool creation, because subscription state cannot be reliably reset when the client is returned. Use a dedicated client for Pub/Sub.
  • Close any WATCH before releasing a client: On release the pool resets state with DISCARD and SELECT, which does not clear a WATCH that was set without a following MULTI. The next borrower inherits that WATCH, so its EXEC can abort over a key it never watched. Always end a WATCH with EXEC, DISCARD, or UNWATCH before returning the client.
  • Limited support for custom per-client callbacks: Support for a language-side custom IAM credentials provider or custom address resolver on a pooled client config varies by binding. Java rejects both at pool creation; Go rejects a custom address resolver; Node.js supports a custom address resolver; Python does not validate either. Where a callback is unsupported, resolve addresses ahead of time and configure IAM without a custom provider.
  • No background eviction: Idle clients are evicted lazily when acquire() is called, not on a background timer.
  • No automatic pool sharing: Each call that creates a pool produces an independent pool. Two pools built from the same configuration are not deduplicated or shared. Hold and reuse the pool you created wherever you need it.
  • Scopes do not outlive the pool: Closing the pool invalidates any isolated scope still open on a borrowed client. Commands on such a scope fail rather than continuing to run on a connection the pool no longer owns.

These are being tracked and are expected to be resolved in a future release.

  • Cluster pools do not reuse connections yet: In cluster mode, a borrowed client’s connection is currently discarded on release instead of being returned to the pool for reuse. Standalone pools reuse connections as expected.
  • The pool can exceed its maximum size under concurrent load: On Node.js and Go, concurrent acquires can create more connections than max_size, and the surplus stays in the pool as idle connections until idle eviction. Allow headroom if you size the pool against a hard server-side connection limit.
  • State reset is unconditional: When a client is returned, the pool resets connection state even if the connection was never mutated. Skipping this work for provably clean connections is planned but not yet implemented.
  • Python can hang after release in cluster mode: A routed command issued on an ordinary cluster client can hang after a pool borrow is released. Avoid reusing a cluster client for routed commands immediately after returning a borrow.
  • Resources can leak on cancelled blocking commands: If an unbounded blocking command (for example BLPOP with a timeout of 0) is cancelled on a borrowed client, the underlying connection may leak. Prefer a non-zero timeout for blocking commands during the preview.
  • Java close() affects shared runtime state: Closing a pool in Java can tear down JVM-wide GLIDE runtime state and affect unrelated clients. Avoid closing a pool while other GLIDE clients are in use in the same process.
  • TLS is not yet enforced for IAM authentication: IAM-authenticated connections are not required to use TLS. Configure TLS explicitly when using IAM auth.