
Redis Connections
- 1.2k installs
- 94 repo stars
- Updated July 9, 2026
- redis/agent-skills
redis-connections guides efficient Redis client setup: pooling, pipelining, safe iteration, client-side caching, and timeouts.
About
Redis Connections teaches client-side efficiency patterns for redis-py, Jedis, Lettuce, go-redis, and NRedisStack across five core areas. It forbids per-request TCP connections in favor of connection pools or multiplexed single connections, noting multiplexed clients cannot carry blocking commands like BLPOP. Pipelining batches independent commands into one round trip, with transactional pipelines reserved for true atomicity needs. Production guidance replaces KEYS, SMEMBERS, HGETALL, and full LRANGE with SCAN-family cursor loops and pagination. RESP3 client-side caching suits read-heavy rarely-written data such as config and feature flags, while explicit socket connect and read timeouts enable fast failure without breaking healthy traffic.
- Pool or multiplex connections; never open TCP per request.
- Pipeline bulk commands for one round trip instead of N serial calls.
- Replace KEYS and full-container reads with SCAN, SSCAN, and HSCAN.
- RESP3 client-side caching for hot read-heavy keys with invalidation.
- Explicit connect and read timeouts with retry-on-timeout tuning guidance.
Redis Connections by the numbers
- 1,240 all-time installs (skills.sh)
- +133 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #79 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
redis-connections capabilities & compatibility
- Capabilities
- connection pool versus multiplex selection by cl · non transactional and transactional pipelining g · scan family replacement for blocking enumeration · resp3 client side caching configuration · connect and read timeout tuning with retry guida
- Use cases
- database · api development
What redis-connections says it does
The single biggest mistake in Redis client code is opening a new TCP connection for every operation.
Anything that walks the whole keyspace (or a whole large container) blocks the server.
npx skills add https://github.com/redis/agent-skills --skill redis-connectionsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.2k |
|---|---|
| repo stars | ★ 94 |
| Last updated | July 9, 2026 |
| Repository | redis/agent-skills ↗ |
How do I configure a Redis client for production throughput without per-request connections or blocking server scans?
Configure efficient Redis clients with pooling or multiplexing, pipelining, SCAN-based iteration, client-side caching, and tuned socket timeouts.
Who is it for?
Backend developers configuring redis-py, Jedis, Lettuce, go-redis, or NRedisStack in latency-sensitive services.
Skip if: Skip for Redis server administration, cluster failover setup, or redis-core transaction semantics alone.
When should I use this skill?
User configures Redis clients, batches commands, iterates large keyspaces, or tunes connect and read timeouts.
What you get
Pooled or multiplexed clients, pipelined batches, SCAN-based iteration, optional RESP3 caching, and explicit timeouts.
- Pooled client configuration
- SCAN-based query patterns
- Pipelining batch plan
By the numbers
- Published as version 1.0.0 in the Redis agent-skills manifest
- Documents four slow-command replacements in a reference table
- Lists six manifest keywords: redis, performance, connections, pooling, pipelining, client-side-cache
Files
Redis Connections
Client-side guidance for talking to Redis efficiently: how to share connections, how to batch commands, which commands not to call in production, when to turn on client-side caching, and how to set timeouts that fail fast without breaking healthy traffic.
When to apply
- Creating or reviewing a Redis client setup (redis-py, Jedis, Lettuce, go-redis, NRedisStack).
- Making many small Redis calls and wondering where the latency is going.
- Iterating large keyspaces, sets, hashes, or lists.
- Enabling client-side caching for hot keys.
- Tuning connect / read / write timeouts.
1. Pool or multiplex — never one connection per request
The single biggest mistake in Redis client code is opening a new TCP connection for every operation. Always either:
- Pool — keep N persistent connections that the application leases per call (redis-py
ConnectionPool, JedisJedisPooled, go-redis client). - Multiplex — share a single connection across all requests (Lettuce, NRedisStack).
| Style | Used by | Note |
|---|---|---|
| Pool | redis-py, Jedis, go-redis | Each lease blocks if pool exhausted; size the pool to your concurrency |
| Multiplex | Lettuce, NRedisStack | Single connection; cannot carry blocking commands like BLPOP |
# redis-py — connection pool
pool = redis.ConnectionPool(host="localhost", port=6379, max_connections=50)
r = redis.Redis(connection_pool=pool)See references/pooling.md for Python + Java + Lettuce examples.
2. Pipeline bulk work
For N commands that don't depend on each other's results, send them as a single batch with pipelining. One round-trip instead of N.
pipe = redis.pipeline()
for user_id in user_ids:
pipe.get(f"user:{user_id}")
results = pipe.execute()Use non-transactional pipelining for performance, and pipeline(transaction=True) only when you actually need atomicity (see redis-core's transactions guidance).
See references/pipelining.md.
3. Avoid commands that scan everything
Anything that walks the whole keyspace (or a whole large container) blocks the server. Use incremental variants instead.
| Don't | Use |
|---|---|
KEYS pattern | SCAN cursor loop |
SMEMBERS large_set | SSCAN |
HGETALL large_hash | HSCAN |
LRANGE 0 -1 on a huge list | Paginate (LRANGE 0 100) |
cursor = 0
while True:
cursor, keys = redis.scan(cursor, match="user:*", count=100)
for key in keys:
process(key)
if cursor == 0:
breakBlocking commands (`BLPOP`, `BRPOP`, `BLMOVE`) are different — they intentionally wait for data and are fine for queue consumers, but always pass a timeout, and don't issue them on a multiplexed connection (Lettuce, NRedisStack).
See references/blocking.md.
4. Client-side caching for hot keys
For data that's read often and written rarely (config, feature flags, sessions on every request), enable RESP3 client-side caching. The client keeps a local copy and the server invalidates it on writes — saving the round trip for hot reads.
client = redis.Redis(
host="localhost",
port=6379,
protocol=3, # RESP3 is required
cache_config=redis.CacheConfig(max_size=1000),
)Skip it for write-heavy workloads or data that changes constantly — the invalidation traffic overruns the savings.
See references/client-cache.md.
5. Set explicit timeouts
Defaults vary by client and may be too generous. Pick values that match the application's failure model:
r = redis.Redis(
host="localhost",
socket_connect_timeout=2.0, # fail fast on dead nodes
socket_timeout=5.0, # tune to expected operation time
retry_on_timeout=True,
)Rule of thumb: connect timeout shorter than read/write timeout. Tight timeouts + retry-on-timeout for latency-sensitive paths; longer timeouts for batch jobs.
See references/timeouts.md.
References
{
"name": "redis-connections",
"version": "1.0.0",
"description": "Redis client and connection guidance — pooling, multiplexing, pipelining, client-side caching, timeouts, slow commands.",
"author": {
"name": "Redis",
"email": "support@redis.com"
},
"homepage": "https://redis.io",
"repository": "https://github.com/redis/agent-skills",
"license": "MIT",
"keywords": ["redis", "performance", "connections", "pooling", "pipelining", "client-side-cache"]
}
Avoid Slow Commands in Production
Some Redis commands are slow because they scan large datasets. Use incremental alternatives to avoid blocking the server.
| Avoid | Use Instead |
|---|---|
KEYS * | SCAN with cursor |
SMEMBERS on large sets | SSCAN |
HGETALL on large hashes | HSCAN |
LRANGE 0 -1 on large lists | Paginate with LRANGE 0 100 |
Correct: Use SCAN for iteration.
Python (redis-py):
# Good: Non-blocking iteration
cursor = 0
while True:
cursor, keys = redis.scan(cursor, match="user:*", count=100)
for key in keys:
process(key)
if cursor == 0:
breakJava (Jedis):
import redis.clients.jedis.ScanIteration;
import redis.clients.jedis.UnifiedJedis;
import java.util.List;
try (UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379")) {
// ScanIteration manages the cursor automatically
ScanIteration scan = jedis.scanIteration(10, "user:*", "hash");
while (!scan.isIterationCompleted()) {
List<String> result = scan.nextBatch().getResult();
for (String key : result) {
process(key);
}
}
}Incorrect: Using KEYS in production.
Python (redis-py):
# Bad: Scans all keys, slow on large datasets
keys = redis.keys("user:*")Java (Jedis):
// Bad: Scans all keys, blocks the server
Set<String> result = jedis.keys("*");Note: Truly blocking commands (like BLPOP, BRPOP, BLMOVE) that wait indefinitely for data are appropriate for some use cases like job queues, but should be used with timeouts.
# Blocking pop with timeout - appropriate for queue consumers
result = redis.blpop("task_queue", timeout=5)Reference: Redis SCAN
Use Client-Side Caching for Frequently Read Data
Use a connection with client-side caching enabled for any data that will be read frequently but written only occasionally. Client-side caching avoids contacting the server for repeated access to data that has recently been read, reducing network traffic and improving performance.
Correct: Enable client-side caching with RESP3 protocol for frequently accessed data.
Python (redis-py):
import redis
# Enable client-side caching with RESP3
client = redis.Redis(
host='localhost',
port=6379,
protocol=3, # RESP3 required for client-side caching
cache_config=redis.CacheConfig(max_size=1000)
)
# Cached reads avoid server round-trips
value = client.get("frequently:read:key")Java (Jedis):
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.UnifiedJedis;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.CacheConfig;
HostAndPort endpoint = new HostAndPort("localhost", 6379);
DefaultJedisClientConfig config = DefaultJedisClientConfig
.builder()
.password("secretPassword")
.protocol(RedisProtocol.RESP3)
.build();
CacheConfig cacheConfig = CacheConfig.builder().maxSize(1000).build();
UnifiedJedis client = new UnifiedJedis(endpoint, config, cacheConfig);When to use:
- Configuration data read frequently, updated rarely
- User session data accessed on every request
- Feature flags or settings checked repeatedly
- Any read-heavy workload with low write frequency
When NOT needed:
- Data that changes frequently (cache invalidation overhead outweighs benefits)
- Write-heavy workloads
- Simple applications where network latency is not a bottleneck
- When you need guaranteed real-time consistency
Trade-offs:
- Adds memory overhead on the client
- Requires RESP3 protocol
- Cache invalidation adds complexity for frequently changing data
Reference: Client-side caching
Use Pipelining for Bulk Operations
Batch multiple commands into a single round trip to reduce network latency.
Correct: Use pipeline for multiple commands.
Python (redis-py):
# Good: Single round trip for multiple commands
pipe = redis.pipeline()
for user_id in user_ids:
pipe.get(f"user:{user_id}")
results = pipe.execute()Java (Jedis):
import redis.clients.jedis.Pipeline;
// Good: Buffer commands and send as single batch
Pipeline pipe = (Pipeline) jedis.pipelined();
pipe.set("person:1:name", "Alex");
pipe.set("person:1:rank", "Captain");
pipe.set("person:1:serial", "AB1234");
pipe.sync();Incorrect: Sequential commands in a loop.
Python (redis-py):
# Bad: N round trips
results = []
for user_id in user_ids:
results.append(redis.get(f"user:{user_id}"))Java (Jedis):
// Bad: 3 separate round trips
jedis.set("person:1:name", "Alex");
jedis.set("person:1:rank", "Captain");
jedis.set("person:1:serial", "AB1234");Reference: Redis Pipelining
Use Connection Pooling or Multiplexing
Reuse connections via a pool or multiplexing instead of creating new connections per request.
Correct: Use a connection pool.
Python (redis-py):
import redis
# Good: Connection pool - reuses existing connections
pool = redis.ConnectionPool(host='localhost', port=6379, max_connections=50)
r = redis.Redis(connection_pool=pool)Java (Jedis):
import redis.clients.jedis.JedisPooled;
// JedisPooled manages a connection pool internally
try (JedisPooled jedis = new JedisPooled("redis://localhost:6379")) {
jedis.set("testKey", "testValue");
}Correct: Use multiplexing (Lettuce, NRedisStack).
// Lettuce uses multiplexing by default - single connection handles all traffic
RedisClient client = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = client.connect();
// All commands share the single connection efficiently
connection.sync().set("key", "value");Incorrect: Creating new connections per request.
Python (redis-py):
# Bad: New connection every time
def get_user(user_id):
r = redis.Redis(host='localhost', port=6379) # Don't do this
return r.get(f"user:{user_id}")Java (Jedis):
// Bad: Creating new client per request
public String getUser(String userId) {
try (UnifiedJedis jedis = new UnifiedJedis("redis://localhost:6379")) {
return jedis.get("user:" + userId); // Don't do this
}
}Pooling vs Multiplexing:
- Pooling: Multiple connections shared across requests (redis-py, Jedis, go-redis)
- Multiplexing: Single connection handles all traffic (NRedisStack, Lettuce)
- Multiplexing cannot support blocking commands (BLPOP, etc.) as they would stall all callers
Reference: Connection Pools and Multiplexing
Configure Connection Timeouts
Configure appropriate timeout values to improve your application's connection resilience. While most Redis clients set default timeouts, choosing well-tuned values based on your application's usage patterns leads to better failure recovery.
Correct: Set timeouts based on your application needs.
r = redis.Redis(
host='localhost',
socket_timeout=5.0, # Read/write timeout - tune based on expected operation time
socket_connect_timeout=2.0, # Connection timeout - shorter for fast failure detection
retry_on_timeout=True # Automatic retry on timeout
)Incorrect: Relying solely on defaults without considering your use case.
# Not ideal: Default timeouts may not match your application's needs
r = redis.Redis(host='localhost')
# For example, if your app needs fast failure detection,
# the default timeouts might be too generousConsiderations:
- Set
socket_connect_timeoutshorter thansocket_timeoutfor quick connection failure detection - For latency-sensitive apps, use tighter timeouts with retry logic
- For batch operations, allow longer timeouts to complete large operations
- Consider using health checks alongside timeouts for robust failure handling
Reference: Redis Client Configuration
Related skills
How it compares
Use redis-connections for client wiring and command safety; pair with Redis data-modeling skills when schema design is the primary question.
FAQ
Pool or multiplex?
Use pools for redis-py and Jedis; multiplex single connections for Lettuce and NRedisStack but not blocking commands.
KEYS or SCAN in production?
Always use SCAN cursor loops; KEYS blocks the server by scanning the entire keyspace.
When enable client-side caching?
For read-heavy rarely-written data like config or feature flags with RESP3 protocol enabled.