Redis Client Management#
Overview#
All Redis client creation in Langfuse flows through a single factory function, createNewRedisInstance(), defined in packages/shared/src/server/redis/redis.ts. This function inspects environment variables to dispatch to one of three modes — standalone, cluster, or Sentinel — and accepts per-call additionalOptions to customize connection behavior for each consumer. A global singleton (redis) is also exported for lightweight use cases that don't need a dedicated connection .
Connection Modes#
createNewRedisInstance() selects a mode at startup :
| Mode | Activation | Entry Point |
|---|---|---|
| Standalone | Default (neither cluster nor sentinel set) | new Redis(REDIS_CONNECTION_STRING) or new Redis({ host, port }) |
| Cluster | REDIS_CLUSTER_ENABLED=true | createRedisClusterInstance() |
| Sentinel | REDIS_SENTINEL_ENABLED=true | createRedisSentinelInstance() |
Cluster and Sentinel modes are mutually exclusive; enabling both returns null with an error log .
Default Options#
All instances share defaultRedisOptions:
enableReadyCheck: truemaxRetriesPerRequest: null(required for BullMQ)keepAlive: 10000ms — prevents middleboxes from killing idle connectionssocketTimeout: 30000ms — forces reconnect if no data is received, preventing hungmoveToCompleted()from blocking concurrency slots
Queue Retry Strategy#
The exported redisQueueRetryOptions object is passed as additionalOptions by all queue and worker factories. It provides:
retryStrategy: exponential backoff from 1 s to 20 s, retries foreverreconnectOnError: reconnects onREADONLYerrors (returns command automatically); ignoresMOVEDcluster redirects
TLS Configuration#
TLS is handled by the shared buildTlsOptions() helper, called inside all three mode constructors. It activates when REDIS_TLS_ENABLED=true and reads certificate/key material from paths (REDIS_TLS_CA_PATH, REDIS_TLS_CERT_PATH, REDIS_TLS_KEY_PATH). Additional TLS knobs: REDIS_TLS_SERVERNAME, REDIS_TLS_REJECT_UNAUTHORIZED, REDIS_TLS_CHECK_SERVER_IDENTITY, REDIS_TLS_CIPHERS, REDIS_TLS_SECURE_PROTOCOL, REDIS_TLS_HONOR_CIPHER_ORDER, REDIS_TLS_KEY_PASSPHRASE. All variables are defined in packages/shared/src/env.ts.
Sentinel Configuration#
createRedisSentinelInstance() requires REDIS_SENTINEL_MASTER_NAME and REDIS_SENTINEL_NODES (comma-separated host:port list). It separates data-node auth (REDIS_AUTH / REDIS_USERNAME) from sentinel-node auth (REDIS_SENTINEL_PASSWORD / REDIS_SENTINEL_USERNAME) .
Known issue (v3.167.4+): The sentinel factory does not set
sentinelRetryStrategy, causing worker connections to permanently break after a failover. See issue #13880 and KB article: Redis Sentinel Integration for details and workaround.
Cluster Utilities#
When REDIS_CLUSTER_ENABLED=true, three utilities handle cluster constraints:
getQueuePrefix(): wraps queue key prefixes in Redis hash tags ({prefix:queueName}) so all keys for a queue land on the same hash slot.safeMultiDel(): serializes multi-keyDELoperations into individual commands to avoidCROSSSLOTerrors.scanKeys(): fans SCAN operations out to all master nodes in cluster mode.
Per-Service Client Factories#
Every service that owns a queue or needs an isolated Redis connection calls createNewRedisInstance() directly. The most relevant non-queue cases:
RateLimitService (web)#
RateLimitService.getInstance() creates a client with lazyConnect: true — the connection is deferred until the first command is sent. It also disables enableOfflineQueue and enableAutoPipelining (to avoid a known ioredis pipelining issue), and includes redisQueueRetryOptions. Rate limiting is skipped entirely when Redis is unavailable (fail-open) .
WorkerManager (worker)#
WorkerManager.register() creates one dedicated Redis connection per registered worker via createNewRedisInstance(redisQueueRetryOptions), giving each BullMQ Worker its own independent connection .
BullMQ Queue Singletons#
All queues under packages/shared/src/server/redis/ follow the same static singleton pattern: a lazy getInstance() that creates a BullMQ Queue with a dedicated createNewRedisInstance({ enableOfflineQueue: false, ...redisQueueRetryOptions }) connection . Sharded queues (Ingestion, OtelIngestion, TraceUpsert, EvalExecution, LLMAsJudge) maintain a Map of instances keyed by shard index .
Global Singleton#
The module-level redis export is a lazily-initialized singleton used by services (e.g., RedisLock) that don't need queue-specific options. In development, it is attached to globalThis to survive hot reloads . It is created with only keyPrefix set, via the private createRedisClient() wrapper.
Key Environment Variables#
Full Zod schema: packages/shared/src/env.ts
| Variable | Purpose |
|---|---|
REDIS_HOST / REDIS_PORT | Standalone host/port |
REDIS_CONNECTION_STRING | Alternative to host+port (takes priority) |
REDIS_AUTH | Data-node password (not REDIS_PASSWORD) |
REDIS_USERNAME | Data-node username |
REDIS_KEY_PREFIX | Key prefix for multi-tenant isolation |
REDIS_ENABLE_AUTO_PIPELINING | Enables auto-pipelining (default true) |
REDIS_TLS_ENABLED | Activates TLS; see REDIS_TLS_* variables for cert paths |
REDIS_CLUSTER_ENABLED + REDIS_CLUSTER_NODES | Cluster mode |
REDIS_SENTINEL_ENABLED + REDIS_SENTINEL_NODES + REDIS_SENTINEL_MASTER_NAME | Sentinel HA mode |
Primary Source Files#
| File | Purpose |
|---|---|
packages/shared/src/server/redis/redis.ts | All Redis factory functions, defaults, retry options, cluster utilities |
packages/shared/src/env.ts | Zod schema for all Redis env vars |
worker/src/queues/workerManager.ts | Per-worker Redis connection creation |
web/src/features/public-api/server/RateLimitService.ts | Lazy-connect Redis client for rate limiting |