Skip to main content

Redis Websocket Support

warning

This tutorial is a community contribution and is not supported by the Open WebUI team. It serves only as a demonstration on how to customize Open WebUI for your specific use case. Want to contribute? Check out the contributing tutorial.

Overview

This documentation page outlines the steps required to integrate Redis with Open WebUI for websocket support. By following these steps, you will be able to enable websocket functionality in your Open WebUI instance, allowing for real-time communication and updates between clients and your application.

When is Redis Required?

Redis serves two distinct purposes in Open WebUI, and understanding when it's required is crucial for proper deployment. For a high-level overview of all scaling requirements (PostgreSQL, Redis, vector DB, storage), see the Scaling Open WebUI guide.

Single Instance Deployments

If you're running Open WebUI as a single instance with UVICORN_WORKERS=1 (the default), Redis is not required for basic functionality. The application will function normally without it for most operations.

Security: Token Revocation Requires Redis

Without Redis, signing out does not invalidate a user's JWT token. The token remains valid and usable until it expires naturally (default: 4 weeks). Password changes and admin-initiated account deactivation also cannot revoke existing tokens without Redis.

For production-facing deployments, either configure Redis or shorten JWT_EXPIRES_IN to limit the window of exposure. See the Hardening guide for details.

Multi-Worker and Multi-Instance Deployments

Redis becomes mandatory in the following scenarios:

  1. Multiple Uvicorn Workers (UVICORN_WORKERS > 1)

    • Running multiple worker processes on a single host
    • Requires Redis to share session state and application configuration between workers
  2. Multi-Node Deployments

    • Kubernetes clusters with multiple pods
    • Docker Swarm with multiple replicas
    • Load-balanced setups with multiple Open WebUI instances
    • Requires Redis to coordinate state across all instances
  3. High Availability Setups

    • Any deployment pattern where multiple Open WebUI processes run simultaneously
    • Requires Redis for session management, websocket coordination, and state synchronization
warning

Critical Requirement

Without Redis in multi-worker or multi-instance scenarios, you will experience:

  • Session management failures across workers
  • Inconsistent application state between instances
  • Non-functional websocket connections
  • Intermittent authentication failures
  • Loss of real-time chat updates

Prerequisites

  • A valid Open WebUI instance (running version 1.0 or higher)
  • A Redis container (we will use redis:7-alpine in this example)
  • Docker Composer (version 2.0 or higher) installed on your system
  • A Docker network for communication between Open WebUI and Redis
  • Basic understanding of Docker, Redis, and Open WebUI

Critical: Redis Server Configuration

danger

Prevent "Max Number of Clients Reached" Errors

Before configuring Open WebUI to use Redis, you must ensure your Redis server itself is properly configured. A common misconfiguration causes connections to accumulate over time, eventually exhausting the connection limit and causing complete authentication failure (500 Internal Server Error for all users).

The Problem:

Open WebUI uses Redis for:

  • Token validation/revocation checking (every authenticated request)
  • WebSocket management (real-time updates)
  • Session storage (if ENABLE_STAR_SESSIONS_MIDDLEWARE is enabled)

With default Redis settings on some distributions (maxclients 1000, timeout 0), connections are never closed. Over days or weeks, they accumulate silently until the limit is reached. Then, suddenly, no one can log in.

The Symptoms:

  • Application works fine for days/weeks
  • Suddenly, all users get 500 Internal Server Error on login
  • Error in logs: redis.exceptions.ConnectionError: max number of clients reached
  • May temporarily "fix itself" as old connections eventually die, then fail again

The Solution:

Add these settings to your Redis configuration:

# Allow sufficient concurrent connections
maxclients 10000

# Close idle connections after 30 minutes (1800 seconds)
# This does NOT affect session validity — only the TCP connection to Redis
timeout 1800

For Docker deployments, add to your Redis command:

services:
  redis:
    image: redis:7-alpine
    command: "redis-server --save 30 1 --appendonly yes --maxclients 10000 --timeout 1800 --maxmemory-policy noeviction"
    # ... rest of config

Why timeout 1800 is safe:

The timeout only affects idle Redis TCP connections, not user sessions. When a connection times out:

  • The user's JWT token remains valid
  • Their session is not affected
  • The next request simply opens a new Redis connection (adds ~1-5ms, imperceptible)

Monitoring:

Check current connection count:

redis-cli INFO clients | grep connected_clients

With proper timeout configuration, this number should fluctuate naturally (rising during active hours, falling during quiet periods) rather than climbing indefinitely.

Critical: Memory Eviction Policy

danger

Do not give Open WebUI's Redis an allkeys-* eviction policy.

Open WebUI uses Redis as a stateful store, not a disposable cache. Its keys fall into two groups:

  • TTL'd security keys — token-revocation entries ({prefix}:auth:token:<jti>:revoked, set to expire exactly when the token would) and distributed locks (set with an expiry).
  • Persistent operational keys — the websocket session and usage pools (Redis hashes with no expiry) and cached configuration.

Under an allkeys-lru, allkeys-lfu, or allkeys-random policy, Redis evicts any key when memory fills, including the two groups above. That can:

  • silently un-revoke a signed-out token — if the revocation key is evicted before its TTL, a token that was invalidated by logout, password change, or admin deactivation starts working again (a security regression), and
  • break websockets, session tracking, and configuration by evicting the persistent pools.

Use noeviction (the safe default). When memory is exhausted, Redis rejects new writes with an error, which is a loud, recoverable signal, instead of silently discarding auth and session state:

maxmemory-policy noeviction

Open WebUI's Redis working set is small (sessions, revocations, locks, config), so with maxmemory left unset Redis simply uses what it needs and never evicts. Only set a maxmemory cap if you have a specific reason to, and if you do, alert on usage rather than relying on eviction.

If you genuinely must cap memory with eviction, the only acceptable policies are volatile-ttl or volatile-lru: these evict only keys that carry a TTL (locks and revocations) and never the persistent pools. Be aware this can still drop a revocation early, so prefer adding RAM over enabling eviction.

Persistence

The example command uses --save 30 1 (an RDB snapshot every 30 minutes, if at least one key changed). On an unclean restart, Redis loses every write since the last snapshot, up to 30 minutes of token revocations and session state, so a crash can resurrect signed-out tokens and drop active sessions.

For production, also enable the append-only file so durability is measured in seconds, not tens of minutes:

appendonly yes
appendfsync everysec

appendfsync everysec flushes the AOF to disk once per second, bounding worst-case loss to roughly one second at a small, usually negligible I/O cost for Open WebUI's modest Redis workload. RDB and AOF coexist; keeping both gives fast restarts plus second-level durability. The example command in the next section already includes --appendonly yes and --maxmemory-policy noeviction.

Setting up Redis

To set up Redis for websocket support, you will need to create a docker-compose.yml file with the following contents:

services:
  redis:
    image: redis:7-alpine
    container_name: redis
    volumes:
      - redis-data:/data
    command: "redis-server --save 30 1 --appendonly yes --maxclients 10000 --timeout 1800 --maxmemory-policy noeviction"
    healthcheck:
      test: "[ $$(redis-cli ping) = 'PONG' ]"
      start_period: 5s
      interval: 1s
      timeout: 3s
      retries: 5
    restart: unless-stopped
    cap_drop:
      - ALL
    cap_add:
      - SETGID
      - SETUID
      - DAC_OVERRIDE
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
        max-file: "1"
    networks:
      - openwebui-network

volumes:
  redis-data:

networks:
  openwebui-network:
    external: true
info

Notes

The ports directive is not included in this configuration, as it is not necessary in most cases. The Redis service will still be accessible from within the Docker network by the Open WebUI service. However, if you need to access the Redis instance from outside the Docker network (e.g., for debugging or monitoring purposes), you can add the ports directive to expose the Redis port (e.g., 6379:6379).

The above configuration sets up a Redis container named redis and mounts a volume for data persistence. The healthcheck directive ensures that the container is restarted if it fails to respond to the ping command. The --save 30 1 command option writes an RDB snapshot every 30 minutes if at least 1 key has changed, and --appendonly yes adds the append-only log for second-level durability.

Important: The --maxclients 10000 --timeout 1800 flags prevent connection exhaustion, and --maxmemory-policy noeviction stops Redis from silently evicting Open WebUI's session and token-revocation keys. See the Critical: Redis Server Configuration, Memory Eviction Policy, and Persistence sections above for details.

WebSocket Pub/Sub Buffer Limits

Open WebUI uses Socket.IO over Redis Pub/Sub when WEBSOCKET_MANAGER=redis is enabled. Streaming responses and tool events can generate large websocket events because some updates include accumulated message state, not only the newest token delta. If Redis disconnects Pub/Sub clients while delivering these events, users can see stalled streams, missing live updates, or log messages such as:

Cannot publish to redis... retrying
Cannot publish to redis... giving up
redis.exceptions.TimeoutError: Timeout connecting to server

Check whether Redis is disconnecting Pub/Sub clients because of output buffer limits:

redis-cli INFO stats | grep client_output_buffer_limit_disconnections
redis-cli SLOWLOG GET 50
redis-cli CONFIG GET client-output-buffer-limit

If the slow log shows large PUBLISH socketio ... payloads and client_output_buffer_limit_disconnections increases, raise the Redis Pub/Sub output buffer limit. For example:

# Keep normal clients unchanged; allow larger websocket Pub/Sub bursts.
client-output-buffer-limit normal 0 0 0 replica 268435456 67108864 60 pubsub 1073741824 268435456 180

This sets the Pub/Sub hard limit to 1 GB and the soft limit to 256 MB for 180 seconds. Tune these values for your available Redis memory and expected websocket payload size. Higher limits make Redis more tolerant of temporary slow subscribers, but they also allow each slow Pub/Sub client to buffer more memory before Redis disconnects it.

If you changed Redis configuration at runtime, verify the active value:

redis-cli CONFIG GET client-output-buffer-limit

To create a Docker network for communication between Open WebUI and Redis, run the following command:

docker network create openwebui-network

Configuring Open WebUI

To enable Redis support in Open WebUI, you need to configure different environment variables depending on your deployment type.

Basic Configuration (All Deployments)

For all deployments using Redis (single or multi-instance), set the following base environment variable:

REDIS_URL="redis://redis:6379/0"

This variable configures the primary Redis connection for application state management, session storage, and coordination between instances.

Websocket Configuration

To enable websocket support specifically, add these additional environment variables:

ENABLE_WEBSOCKET_SUPPORT="true"
WEBSOCKET_MANAGER="redis"
WEBSOCKET_REDIS_URL="redis://redis:6379/1"
Critical: Configure CORS for WebSocket Connections

A very common and difficult-to-debug issue with WebSocket connections is a misconfigured Cross-Origin Resource Sharing (CORS) policy. If your Open WebUI instance is accessed from a different domain or port than the backend (e.g., behind a reverse proxy), you must set the CORS_ALLOW_ORIGIN environment variable. This variable tells the server which origins are permitted to access its resources.

Failure to configure this correctly will cause WebSocket connections to fail silently or with cryptic browser errors and forgetting to set this variable is a common cause of WebSocket connection issues.

Example: If you access your UI at https://my-open-webui.com, you must set:

CORS_ALLOW_ORIGIN="https://my-open-webui.com"

You can also provide a semicolon-separated list of allowed domains. Do not skip this step in a production or reverse-proxied setup.

info

Redis Database Numbers

Notice the different database numbers (/0 vs /1) in the URLs:

  • REDIS_URL uses database 0 for general application state
  • WEBSOCKET_REDIS_URL uses database 1 for websocket-specific data

This separation helps isolate different types of data. You can use the same database number for both if preferred, but using separate databases is recommended for better organization and potential performance optimization.

Optional Configuration

REDIS_KEY_PREFIX="open-webui"

The REDIS_KEY_PREFIX allows multiple Open WebUI instances to share the same Redis instance without key conflicts. In Redis cluster mode, the prefix is formatted as {prefix}: (e.g., {open-webui}:config:*) to enable multi-key operations on configuration keys within the same hash slot.

Sentinel Failover Configuration

Critical: Socket Timeout for Sentinel Deployments

Redis Sentinel setups require explicit socket connection timeout configuration to ensure proper failover behavior. Without a timeout, the application can hang indefinitely when a Redis master node goes offline, potentially preventing even application restarts.

Symptoms of missing timeout configuration:

  • Application becomes completely unresponsive during failover
  • Application hangs on startup if the first Sentinel host is unreachable
  • Recovery takes minutes instead of seconds after master failover

Required configuration:

REDIS_SOCKET_CONNECT_TIMEOUT=5

This sets a 5-second timeout for socket connection attempts to Redis/Sentinel nodes, allowing the application to fail over gracefully.

warning

If using WEBSOCKET_REDIS_OPTIONS

When you explicitly set WEBSOCKET_REDIS_OPTIONS, REDIS_SOCKET_CONNECT_TIMEOUT does not automatically apply to websocket connections. You must include the timeout in both places:

REDIS_SOCKET_CONNECT_TIMEOUT=5
WEBSOCKET_REDIS_OPTIONS='{"socket_connect_timeout": 5}'

Retry and Reconnect Logic

To enhance resilience during Sentinel failover (the window when a new master is being elected and promoted) you can configure retry behavior to prevent the application from exhausting its reconnection attempts too quickly.

  • REDIS_SENTINEL_MAX_RETRY_COUNT: Sets the maximum number of retries for Redis operations when using Sentinel (Default: 2).
  • REDIS_RECONNECT_DELAY: Adds an optional delay in milliseconds between retry attempts (e.g., REDIS_RECONNECT_DELAY=500). This prevents tight retry loops that may otherwise overwhelm the event loop or block the application before a new master is ready.

Connection Health Checks

If your Redis server has a timeout configured (recommended, see above), pooled connections that sit idle longer than that timeout will be reaped server-side. Without health checks, the next request that grabs one of those dead sockets will fail with ConnectionError: Connection reset by peer.

  • REDIS_HEALTH_CHECK_INTERVAL: How often (in seconds) redis-py should PING an idle pooled connection before reusing it (e.g., REDIS_HEALTH_CHECK_INTERVAL=60). The value must be shorter than your Redis server's timeout and any firewall/load balancer idle timeout on the path to Redis. Set to 0 or leave empty to disable.
  • REDIS_SOCKET_KEEPALIVE: Enables TCP SO_KEEPALIVE on all Redis client sockets (e.g., REDIS_SOCKET_KEEPALIVE=True). When enabled, the OS kernel sends TCP keepalive probes on idle connections, detecting half-closed sockets caused by silent firewall/load balancer resets or network flaps at the TCP level.

These two mechanisms are complementary:

  • REDIS_HEALTH_CHECK_INTERVAL works at the application level: redis-py PINGs idle connections on checkout, validating the socket and resetting the server's idle timer.
  • REDIS_SOCKET_KEEPALIVE works at the TCP level: the kernel detects dead peers even when no application-level traffic is flowing.
Recommended pairing

For robust production deployments, configure all three layers together:

MechanismLevelCoversExample
timeout 1800 (redis.conf)ServerReaps leaked/orphaned connections the app forgot aboutSafety net
REDIS_HEALTH_CHECK_INTERVAL=60ApplicationDetects dead sockets before real commands use them; keeps pooled connections aliveActive protection
REDIS_SOCKET_KEEPALIVE=TrueTCP/KernelDetects half-closed sockets from silent network resets (firewalls, LBs, NIC flaps)Network-level protection

Redis Cluster Mode

For deployments using Redis Cluster (including managed services like AWS Elasticache Serverless), enable cluster mode with the following configuration:

REDIS_URL="redis://your-cluster-endpoint:6379/0"
REDIS_CLUSTER="true"
info

Key Configuration Notes

  • REDIS_CLUSTER enables cluster-aware connection handling
  • The REDIS_URL should point to your cluster's configuration endpoint
  • This option has no effect if REDIS_SENTINEL_HOSTS is defined (Sentinel takes precedence)
  • When using cluster mode, the REDIS_KEY_PREFIX is automatically formatted as {prefix}: to ensure multi-key operations target the same hash slot

AWS Elasticache Serverless

For AWS Elasticache Serverless deployments, use the following configuration:

REDIS_URL="rediss://your-elasticache-endpoint.serverless.use1.cache.amazonaws.com:6379/0"
REDIS_CLUSTER="true"

Note the rediss:// scheme (with double 's') which enables TLS, required for Elasticache Serverless.

OpenTelemetry Support

Redis Cluster mode is fully compatible with OpenTelemetry instrumentation. When ENABLE_OTEL is enabled, Redis operations are properly traced regardless of whether you're using a single Redis instance, Redis Sentinel, or Redis Cluster mode.

Complete Example Configuration

Here's a complete example showing all Redis-related environment variables:

# Required for multi-worker/multi-instance deployments
REDIS_URL="redis://redis:6379/0"

# Required for websocket support
ENABLE_WEBSOCKET_SUPPORT="true"
WEBSOCKET_MANAGER="redis"
WEBSOCKET_REDIS_URL="redis://redis:6379/1"

# Recommended for Sentinel deployments (prevents failover hangs)
REDIS_SOCKET_CONNECT_TIMEOUT=5
REDIS_SENTINEL_MAX_RETRY_COUNT=5
REDIS_RECONNECT_DELAY=1000

# Recommended: detect stale pooled connections (must be < Redis server timeout)
REDIS_HEALTH_CHECK_INTERVAL=60

# Recommended: enable TCP keepalive for dead-peer detection at the kernel level
REDIS_SOCKET_KEEPALIVE=True

# Optional
REDIS_KEY_PREFIX="open-webui"

For Redis Sentinel deployments specifically, ensure REDIS_SOCKET_CONNECT_TIMEOUT is set to prevent application hangs during master failover.

Redis Cluster Mode Example

For Redis Cluster deployments (including AWS Elasticache Serverless):

# Required for Redis Cluster
REDIS_URL="rediss://your-cluster-endpoint:6379/0"
REDIS_CLUSTER="true"

# Required for websocket support
ENABLE_WEBSOCKET_SUPPORT="true"
WEBSOCKET_MANAGER="redis"
WEBSOCKET_REDIS_URL="rediss://your-cluster-endpoint:6379/0"
WEBSOCKET_REDIS_CLUSTER="true"

# Optional
REDIS_KEY_PREFIX="open-webui"

Docker Run Example

When running Open WebUI using Docker, connect it to the same Docker network and include all necessary Redis variables:

docker run -d \
  --name open-webui \
  --network openwebui-network \
  -v open-webui:/app/backend/data \
  -p 3000:8080 \
  -e REDIS_URL="redis://redis:6379/0" \
  -e ENABLE_WEBSOCKET_SUPPORT="true" \
  -e WEBSOCKET_MANAGER="redis" \
  -e WEBSOCKET_REDIS_URL="redis://redis:6379/1" \
  -e REDIS_KEY_PREFIX="open-webui" \
  ghcr.io/open-webui/open-webui:main
warning

Important Note on Service Names

In the examples above, we use redis://redis:6379 because:

  • redis is the container name defined in the docker-compose.yml
  • Docker's internal DNS resolves this name to the correct IP address within the network
  • This is the recommended approach for Docker deployments

Do not use 127.0.0.1 or localhost when connecting from one container to another. These refer to the container's own localhost, not the Redis container.

Multi-Worker Configuration

If you're running multiple Uvicorn workers on a single host, add this variable:

UVICORN_WORKERS="4"  # Adjust based on your CPU cores
REDIS_URL="redis://redis:6379/0"  # Required when UVICORN_WORKERS > 1
danger

Critical: Redis Required for UVICORN_WORKERS > 1

If you set UVICORN_WORKERS to any value greater than 1, you must configure REDIS_URL. Failing to do so will cause:

  • Session state to be lost between requests
  • Authentication to fail intermittently
  • Application configuration to be inconsistent
  • Websockets to malfunction
danger

Critical: Default ChromaDB (SQLite) Not Compatible with Multiple Workers

In addition to Redis, you must also address the vector database. The default ChromaDB uses a local SQLite-backed PersistentClient that is not fork-safe. When uvicorn forks multiple workers, concurrent writes to the same SQLite file will crash workers instantly during document uploads (Child process died).

You must either:

  • Switch to a client-server vector database (VECTOR_DB=pgvector, mariadb-vector, milvus, or qdrant)
  • Run ChromaDB as a separate HTTP server and set CHROMA_HTTP_HOST / CHROMA_HTTP_PORT

See the Scaling & HA guide for details.

Verification

Verify Redis Connection

First, confirm that your Redis instance is running and accepting connections:

docker exec -it redis redis-cli -p 6379 ping

This command should output PONG if the Redis instance is running correctly.

Verify Open WebUI Configuration

After starting your Open WebUI instance with the proper Redis configuration, check the logs to confirm successful integration:

Check for General Redis Connection

Look for log messages indicating Redis is being used for application state:

docker logs open-webui 2>&1 | grep -i redis

Check for Websocket Redis Connection

If you have enabled websocket support, you should see this specific log message:

DEBUG:open_webui.socket.main:Using Redis to manage websockets.

To check this specifically:

docker logs open-webui 2>&1 | grep "Using Redis to manage websockets"

Verify Redis Keys

You can also verify that Open WebUI is actually writing data to Redis:

docker exec -it redis redis-cli --scan --pattern "open-webui*"

If Redis is configured correctly, you should see keys with your configured prefix (e.g., open-webui:session:*, open-webui:config:*).

Test Multi-Worker Setup

If you're running with UVICORN_WORKERS > 1, test that sessions persist across workers:

  1. Log in to Open WebUI
  2. Refresh the page multiple times
  3. You should remain logged in consistently

If you're logged out randomly or see authentication errors, Redis is likely not configured correctly.

Troubleshooting

Common Issues and Solutions

Issue: "Connection to Redis failed"

Symptoms:

  • Error messages about Redis connection in logs
  • Application fails to start or crashes
  • Websockets don't work

Solutions:

  1. Verify Redis container is running: docker ps | grep redis
  2. Check Redis is healthy: docker exec -it redis redis-cli ping
  3. Verify network connectivity: docker network inspect openwebui-network
  4. Ensure the REDIS_URL uses the correct container name, not 127.0.0.1 or localhost
  5. Check that both containers are on the same Docker network

Issue: "Session lost after page refresh" (with UVICORN_WORKERS > 1)

Symptoms:

  • Users are logged out randomly
  • Authentication works but doesn't persist
  • Different behavior on each page refresh

Cause: REDIS_URL is not configured when using multiple workers

Solution: Add the REDIS_URL environment variable:

REDIS_URL="redis://redis:6379/0"

Issue: "Websockets not working"

Symptoms:

  • Real-time chat updates don't appear
  • Need to refresh page to see new messages
  • Connection errors in browser console

Solutions:

  1. Verify all websocket environment variables are set:
    • ENABLE_WEBSOCKET_SUPPORT="true"
    • WEBSOCKET_MANAGER="redis"
    • WEBSOCKET_REDIS_URL="redis://redis:6379/1"
  2. Check logs for: DEBUG:open_webui.socket.main:Using Redis to manage websockets.
  3. Verify Redis is accessible from Open WebUI container

Issue: "Multiple Open WebUI instances interfering with each other"

Symptoms:

  • Configuration changes affect other instances
  • Sessions conflict between deployments
  • Unexpected behavior when running multiple Open WebUI installations

Solution: Use different REDIS_KEY_PREFIX values for each installation:

# Instance 1
REDIS_KEY_PREFIX="openwebui-prod"

# Instance 2
REDIS_KEY_PREFIX="openwebui-dev"

Issue: "Redis memory usage growing continuously"

Symptoms:

  • Redis memory usage increases over time
  • Container eventually runs out of memory
danger

Do not "fix" this with --maxmemory-policy allkeys-lru. Open WebUI's Redis holds token-revocation keys, session pools, and locks, not disposable cache. An allkeys-* policy can silently un-revoke a signed-out token and break sessions. See Memory Eviction Policy.

Continuously growing memory usually means key growth, not a missing eviction policy, so investigate the cause rather than masking it with eviction.

Solutions:

  1. Find what is consuming memory and whether it is growing without bound:

    docker exec -it redis redis-cli info memory
    docker exec -it redis redis-cli --bigkeys
    docker exec -it redis redis-cli info keyspace   # key counts per DB
  2. Confirm timeout is set (idle-connection accumulation also shows up as memory growth), per the Critical: Redis Server Configuration section.

  3. If you must cap memory, set a maxmemory limit paired with noeviction so Redis fails writes loudly instead of dropping auth/session state, then alert on used_memory:

    maxmemory 512mb
    maxmemory-policy noeviction
  4. Avoid FLUSHDB/FLUSHALL on a live instance: it wipes active sessions, the revocation list, and locks. Restart the Redis container instead if you need to clear accumulated state during a maintenance window.

Issue: "max number of clients reached" after days/weeks of operation

Symptoms:

  • Application worked fine for an extended period, then suddenly fails
  • All login attempts return 500 Internal Server Error
  • Error in logs: redis.exceptions.ConnectionError: max number of clients reached
  • May temporarily recover, then fail again

Cause: Redis maxclients limit reached due to connection accumulation. This happens when:

  • timeout is set to 0 (connections never close)
  • maxclients is too low for your usage pattern

Solution:

  1. Check current connection count:

    redis-cli INFO clients | grep connected_clients
  2. Check current settings:

    redis-cli CONFIG GET maxclients
    redis-cli CONFIG GET timeout
  3. Fix the configuration:

    redis-cli CONFIG SET maxclients 10000
    redis-cli CONFIG SET timeout 1800
  4. Make permanent by adding to redis.conf or Docker command:

    maxclients 10000
    timeout 1800
  5. Restart Redis to clear accumulated connections:

    # For systemd
    sudo systemctl restart redis
    
    # For Docker
    docker restart redis

Prevention: Always configure timeout to a reasonable value (e.g., 1800 seconds). The timeout only affects idle TCP connections, not user sessions. It's safe and recommended. Pair this with REDIS_HEALTH_CHECK_INTERVAL on the client side (see below).

Issue: "Connection reset by peer" errors on first request after idle period

Symptoms:

  • Sporadic redis.exceptions.ConnectionError: Connection reset by peer in logs
  • Errors tend to appear after periods of low activity (nights, weekends)
  • The request that triggers the error fails with a 500 Internal Server Error, but subsequent requests succeed
  • More common when Redis server timeout is configured (which it should be, see above)

Cause: The Redis server reaped an idle connection (via its timeout setting), but the pooled socket in redis-py was not aware it was dead. The next request that grabbed that socket from the pool sent a command to a closed connection.

Solution:

Set the REDIS_HEALTH_CHECK_INTERVAL environment variable to a value shorter than your Redis server's timeout:

# Redis server timeout is 1800s (30 min), so check every 60s
REDIS_HEALTH_CHECK_INTERVAL=60

This tells redis-py to PING any pooled connection that has been idle for more than 60 seconds before reusing it. If the connection is dead, it is replaced transparently. The PING also resets the server's idle timer, keeping actively-used connections alive.

How to choose the right value:

Your Redis timeoutSuggested REDIS_HEALTH_CHECK_INTERVAL
300 (5 min)30
900 (15 min)60
1800 (30 min)60
3600 (1 hour)120

The health check interval should also be shorter than any firewall or load balancer idle timeout between the application and Redis.

Additional Resources

Getting Help

If you continue to experience issues after following this guide:

  1. Check the Open WebUI GitHub Issues
  2. Review your complete configuration for typos
  3. Verify all containers can communicate on the Docker network
  4. Collect relevant logs from both Open WebUI and Redis containers
  5. Join the Open WebUI Discord for community support

By following these steps and troubleshooting tips, you should be able to set up Redis with Open WebUI for both application state management and websocket support, enabling reliable multi-instance deployments and real-time communication between clients and your application.

This content is for informational purposes only and does not constitute a warranty, guarantee, or contractual commitment. Open WebUI is provided "as is." See your license for applicable terms.