Redis Connection Management#
Redis is a central dependency in Dify, used for caching, distributed locking, pub/sub event delivery (SSE streams, Socket.IO collaboration), and Celery task brokering. Connection configuration lives in RedisConfig (Pydantic BaseSettings, all fields readable from env vars), and the client is initialized in ext_redis.py.
Configuration Reference#
All settings are in api/configs/middleware/cache/redis_config.py.
Connection basics
REDIS_HOST(defaultlocalhost),REDIS_PORT(default6379),REDIS_DB(default0)REDIS_USERNAME,REDIS_PASSWORDβ optional authREDIS_KEY_PREFIXβ global prefix applied to all keys/channel names; prevents cross-deployment collisions on shared instances
Timeouts & pool
REDIS_SOCKET_TIMEOUT(default5.0s) β per-operation read/write timeoutREDIS_SOCKET_CONNECT_TIMEOUT(default5.0s) β TCP connection establishment timeoutREDIS_HEALTH_CHECK_INTERVAL(default30s) β periodic ping to detect stale connections (not supported by Cluster; silently excluded)REDIS_MAX_CONNECTIONSβ optional pool size cap
Retry policy
REDIS_RETRY_RETRIES(default3),REDIS_RETRY_BACKOFF_BASE(default1.0s),REDIS_RETRY_BACKOFF_CAP(default10.0s)- Uses
ExponentialWithJitterBackoff; retries onConnectionError,TimeoutError,BrokenPipeError,OSError
TCP Keepalive β added in PR #38973
REDIS_KEEPALIVE(defaultfalse) β enables TCP keepalive on the socketREDIS_KEEPALIVE_IDLE(default30s),REDIS_KEEPALIVE_INTERVAL(default10s),REDIS_KEEPALIVE_COUNT(default10)- Platform-specific: Linux sets
TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT; macOS setsTCP_KEEPALIVE
SSL/TLS
REDIS_USE_SSLβ switches toSSLConnectionandrediss://schemeREDIS_SSL_CERT_REQS,REDIS_SSL_CA_CERTS,REDIS_SSL_CERTFILE,REDIS_SSL_KEYFILE
RESP protocol / client-side cache
REDIS_SERIALIZATION_PROTOCOL(default3)REDIS_ENABLE_CLIENT_SIDE_CACHEβ requires RESP3; enforced at startup
Client Types#
init_app() selects one of three factory functions based on config flags:
| Mode | Trigger flag | Factory |
|---|---|---|
| Standalone (default) | (none) | _create_standalone_client() β builds a ConnectionPool |
| Sentinel | REDIS_USE_SENTINEL=true | _create_sentinel_client() β requires REDIS_SENTINELS and REDIS_SENTINEL_SERVICE_NAME |
| Cluster | REDIS_USE_CLUSTERS=true | _create_cluster_client() β requires REDIS_CLUSTERS |
Cluster caveat: health_check_interval is silently ignored by RedisCluster, so _get_cluster_connection_health_params() explicitly excludes it.
The global redis_client is a RedisClientWrapper that transparently prefixes all key/name arguments using REDIS_KEY_PREFIX and supports deferred initialization to handle Sentinel failover β the inner _client is only set once and can be swapped by re-calling initialize() .
Pub/Sub Clients#
A separate pub/sub client (_pubsub_redis_client) is initialized in init_app(). By default it reuses the main client. If PUBSUB_REDIS_URL is set, a dedicated client is created via _create_pubsub_client() β which supports both standalone and Cluster modes from a URL.
get_pubsub_broadcast_channel() returns one of three channel implementations based on PUBSUB_REDIS_CHANNEL_TYPE:
| Value | Implementation |
|---|---|
pubsub (default) | RedisBroadcastChannel |
sharded | ShardedRedisBroadcastChannel |
streams | StreamsBroadcastChannel (configurable retention via PUBSUB_STREAMS_RETENTION_SECONDS) |
Ongoing refactor (PR #35515): A pending PR replaces the URL-based pub/sub config with a structured
RedisConnectionSpecfrozen dataclass. This will unify main and pub/sub client construction for all three topologies (including Sentinel HA for pub/sub, which silently degraded before) and replacePUBSUB_REDIS_URLwith structuredPUBSUB_REDIS_*fields. See PR #35515 .
Socket.IO Integration#
ext_socketio.py uses socketio.RedisManager to fan out collaboration room events across API workers. The channel name is serialize_redis_name("socketio"), which applies REDIS_KEY_PREFIX for deployment isolation .
Critical: socket_timeout is intentionally omitted from RedisManager options . The RedisManager runs a blocking pubsub.listen() loop that idles between messages indefinitely; passing REDIS_SOCKET_TIMEOUT (default 5s) causes a reconnect storm every quiet 5-second window (TimeoutError β resubscribe), breaking collaboration event delivery. This was fixed in PR #39587. socket_connect_timeout is still passed to guard connection establishment.
Key Files#
| File | Purpose |
|---|---|
api/configs/middleware/cache/redis_config.py | All REDIS_* env var definitions and defaults |
api/extensions/ext_redis.py | Client factory, RedisClientWrapper, retry/keepalive logic, pub/sub client |
api/extensions/ext_socketio.py | Socket.IO RedisManager setup; socket_timeout intentionally omitted |