Skip to main content
Open WebUI supports horizontal scaling with Redis for multi-worker and multi-node deployments behind load balancers. This enables high-availability, fault-tolerant production deployments.

Overview

Redis provides:
  • Distributed Sessions - Share user sessions across multiple instances
  • WebSocket State - Synchronized real-time connections across workers
  • Configuration Sync - Propagate runtime config changes to all nodes
  • Task Coordination - Distributed task management and pub/sub
  • Rate Limiting - Centralized rate limit tracking
  • Token Revocation - Shared JWT token blacklist

Prerequisites

  • Redis server (standalone, cluster, or Sentinel)
  • Load balancer (nginx, HAProxy, AWS ALB, etc.)
  • Multiple Open WebUI instances

Redis Configuration

Standalone Redis

Basic Redis connection:
# Redis connection URL
REDIS_URL=redis://redis-server:6379

# Optional: Redis key prefix (for multi-tenant deployments)
REDIS_KEY_PREFIX=open-webui

# Optional: Socket connection timeout (milliseconds)
REDIS_SOCKET_CONNECT_TIMEOUT=5000

# Optional: Reconnect delay after connection failure (milliseconds)
REDIS_RECONNECT_DELAY=1000

Redis with Authentication

REDIS_URL=redis://:password@redis-server:6379
# Or with username (Redis 6+)
REDIS_URL=redis://username:password@redis-server:6379

Redis with TLS/SSL

REDIS_URL=rediss://redis-server:6380  # Note: rediss:// for TLS

Redis Cluster

For Redis Cluster deployments:
REDIS_URL=redis://node1:6379,node2:6379,node3:6379
REDIS_CLUSTER=true

Redis Sentinel

For high-availability Redis Sentinel:
# Comma-separated Sentinel hosts
REDIS_SENTINEL_HOSTS=sentinel1:26379,sentinel2:26379,sentinel3:26379
REDIS_SENTINEL_PORT=26379

# Master name configured in Sentinel
REDIS_URL=redis://mymaster

# Sentinel retry configuration
REDIS_SENTINEL_MAX_RETRY_COUNT=3
REDIS_RECONNECT_DELAY=1000

Session Management

Redis-backed sessions enable stateless application servers:
# Enable session middleware (required for multi-instance)
ENABLE_STAR_SESSIONS_MIDDLEWARE=true

# Redis URL for session storage
REDIS_URL=redis://redis-server:6379

Session Configuration

# Session cookie settings
WEBUI_SESSION_COOKIE_SAME_SITE=lax  # or 'strict', 'none'
WEBUI_SESSION_COOKIE_SECURE=true  # Require HTTPS

# JWT expiration
JWT_EXPIRES_IN=4w  # 4 weeks, or '7d', '24h', '-1' for never

WebSocket Scaling

Redis enables WebSocket connections across multiple instances:
  • Real-time chat updates synchronized
  • Task status notifications broadcast
  • Multi-node pub/sub messaging
Automatic - WebSocket support is automatically enabled when REDIS_URL is configured.

Persistent Configuration

Enable runtime configuration updates across all instances:
# Enable persistent config with Redis sync
ENABLE_PERSISTENT_CONFIG=true
REDIS_URL=redis://redis-server:6379
REDIS_KEY_PREFIX=open-webui
Configuration changes via Admin UI are:
  1. Saved to database
  2. Published to Redis
  3. Applied to all running instances

Docker Compose Example

Multi-Instance Deployment with Redis

version: '3'

services:
  # Redis for session and state management
  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    restart: always
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  # PostgreSQL database
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: openwebui
      POSTGRES_USER: openwebui
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    restart: always

  # Open WebUI instance 1
  open-webui-1:
    image: ghcr.io/open-webui/open-webui:main
    environment:
      # Database
      - DATABASE_URL=postgresql://openwebui:${POSTGRES_PASSWORD}@postgres:5432/openwebui
      
      # Redis Configuration
      - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379
      - REDIS_KEY_PREFIX=open-webui
      - ENABLE_STAR_SESSIONS_MIDDLEWARE=true
      - ENABLE_PERSISTENT_CONFIG=true
      
      # Instance identification
      - INSTANCE_ID=instance-1
    volumes:
      - open-webui-data:/app/backend/data
    depends_on:
      - redis
      - postgres
    restart: always

  # Open WebUI instance 2
  open-webui-2:
    image: ghcr.io/open-webui/open-webui:main
    environment:
      - DATABASE_URL=postgresql://openwebui:${POSTGRES_PASSWORD}@postgres:5432/openwebui
      - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379
      - REDIS_KEY_PREFIX=open-webui
      - ENABLE_STAR_SESSIONS_MIDDLEWARE=true
      - ENABLE_PERSISTENT_CONFIG=true
      - INSTANCE_ID=instance-2
    volumes:
      - open-webui-data:/app/backend/data
    depends_on:
      - redis
      - postgres
    restart: always

  # Open WebUI instance 3
  open-webui-3:
    image: ghcr.io/open-webui/open-webui:main
    environment:
      - DATABASE_URL=postgresql://openwebui:${POSTGRES_PASSWORD}@postgres:5432/openwebui
      - REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379
      - REDIS_KEY_PREFIX=open-webui
      - ENABLE_STAR_SESSIONS_MIDDLEWARE=true
      - ENABLE_PERSISTENT_CONFIG=true
      - INSTANCE_ID=instance-3
    volumes:
      - open-webui-data:/app/backend/data
    depends_on:
      - redis
      - postgres
    restart: always

  # Nginx load balancer
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - open-webui-1
      - open-webui-2
      - open-webui-3
    restart: always

volumes:
  redis-data:
  postgres-data:
  open-webui-data:

Nginx Load Balancer Configuration

nginx.conf:
upstream open_webui_backend {
    least_conn;  # Use least connections algorithm
    
    server open-webui-1:8080 max_fails=3 fail_timeout=30s;
    server open-webui-2:8080 max_fails=3 fail_timeout=30s;
    server open-webui-3:8080 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name openwebui.company.com;
    
    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name openwebui.company.com;
    
    # SSL Configuration
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    
    # Client upload size
    client_max_body_size 100M;
    
    # WebSocket support
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # Proxy headers
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    
    # Timeouts
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
    
    location / {
        proxy_pass http://open_webui_backend;
        
        # WebSocket keepalive
        proxy_set_header Connection "upgrade";
        proxy_set_header Upgrade $http_upgrade;
        
        # Disable buffering for streaming responses
        proxy_buffering off;
    }
}

Cloud Deployments

AWS with Application Load Balancer

# Environment variables for ECS/EKS
DATABASE_URL=postgresql://user:pass@rds-endpoint:5432/openwebui
REDIS_URL=redis://elasticache-endpoint:6379
ENABLE_STAR_SESSIONS_MIDDLEWARE=true
ENABLE_PERSISTENT_CONFIG=true

# ALB handles SSL termination
WEBUI_SESSION_COOKIE_SECURE=true
ALB Configuration:
  • Target Group: Multiple Open WebUI instances
  • Health Check: /health endpoint
  • Stickiness: Not required (Redis sessions)
  • WebSocket: Enable WebSocket upgrade headers

Kubernetes with Ingress

apiVersion: apps/v1
kind: Deployment
metadata:
  name: open-webui
spec:
  replicas: 3
  selector:
    matchLabels:
      app: open-webui
  template:
    metadata:
      labels:
        app: open-webui
    spec:
      containers:
      - name: open-webui
        image: ghcr.io/open-webui/open-webui:main
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
        - name: REDIS_URL
          value: "redis://redis-service:6379"
        - name: ENABLE_STAR_SESSIONS_MIDDLEWARE
          value: "true"
        - name: ENABLE_PERSISTENT_CONFIG
          value: "true"
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: data
          mountPath: /app/backend/data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: open-webui-data
---
apiVersion: v1
kind: Service
metadata:
  name: open-webui
spec:
  selector:
    app: open-webui
  ports:
  - port: 8080
    targetPort: 8080
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: open-webui
  annotations:
    nginx.ingress.kubernetes.io/websocket-services: open-webui
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - openwebui.company.com
    secretName: tls-secret
  rules:
  - host: openwebui.company.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: open-webui
            port:
              number: 8080

Redis High Availability

Redis Sentinel

For production deployments with automatic failover:
version: '3'

services:
  redis-master:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-master:/data

  redis-replica-1:
    image: redis:7-alpine
    command: redis-server --replicaof redis-master 6379 --requirepass ${REDIS_PASSWORD} --masterauth ${REDIS_PASSWORD}
    volumes:
      - redis-replica-1:/data
    depends_on:
      - redis-master

  redis-replica-2:
    image: redis:7-alpine
    command: redis-server --replicaof redis-master 6379 --requirepass ${REDIS_PASSWORD} --masterauth ${REDIS_PASSWORD}
    volumes:
      - redis-replica-2:/data
    depends_on:
      - redis-master

  sentinel-1:
    image: redis:7-alpine
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master

  sentinel-2:
    image: redis:7-alpine
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master

  sentinel-3:
    image: redis:7-alpine
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./sentinel.conf:/etc/redis/sentinel.conf
    depends_on:
      - redis-master

  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    environment:
      - REDIS_URL=redis://mymaster
      - REDIS_SENTINEL_HOSTS=sentinel-1:26379,sentinel-2:26379,sentinel-3:26379
      - REDIS_SENTINEL_PORT=26379
      - REDIS_SENTINEL_MAX_RETRY_COUNT=3
      - ENABLE_STAR_SESSIONS_MIDDLEWARE=true

volumes:
  redis-master:
  redis-replica-1:
  redis-replica-2:
sentinel.conf:
port 26379
sentinel monitor mymaster redis-master 6379 2
sentinel auth-pass mymaster ${REDIS_PASSWORD}
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000

Monitoring and Health Checks

Health Check Endpoint

curl http://localhost:8080/health
Returns:
{
  "status": "ok",
  "version": "0.3.0"
}

Redis Connection Check

# Test Redis connectivity
redis-cli -h redis-server -p 6379 -a password PING
# Should return: PONG

Monitor Redis Keys

# View session keys
redis-cli -h redis-server -p 6379 -a password KEYS "open-webui:*"

# Monitor real-time commands
redis-cli -h redis-server -p 6379 -a password MONITOR

Troubleshooting

Redis Connection Failures

Problem: Cannot connect to Redis Check:
# Test Redis connectivity
telnet redis-server 6379

# Check Redis logs
docker logs redis-container

# Verify credentials
redis-cli -h redis-server -p 6379 -a password PING

Session Loss

Problem: Users logged out frequently Check:
  • Redis is running and accessible
  • ENABLE_STAR_SESSIONS_MIDDLEWARE=true is set
  • REDIS_URL is correctly configured
  • Redis has sufficient memory (check INFO memory)

WebSocket Disconnections

Problem: Real-time features not working Check:
  • Load balancer supports WebSocket upgrades
  • Nginx: proxy_set_header Upgrade $http_upgrade;
  • ALB: Enable WebSocket support
  • Redis pub/sub is functioning

Configuration Not Syncing

Problem: Config changes not applied to all instances Check:
  • ENABLE_PERSISTENT_CONFIG=true on all instances
  • All instances use same REDIS_URL
  • Redis pub/sub channels working: redis-cli PUBSUB CHANNELS

Performance Tuning

Redis Optimization

# Increase max connections
maxclients 10000

# Enable persistence for session durability
save 900 1
save 300 10
save 60 10000

# Memory policy
maxmemory 2gb
maxmemory-policy allkeys-lru

Connection Pooling

Open WebUI automatically manages Redis connection pools. Adjust if needed:
# Socket timeout (milliseconds)
REDIS_SOCKET_CONNECT_TIMEOUT=5000

# Reconnect delay after failure (milliseconds)
REDIS_RECONNECT_DELAY=1000

Implementation Details

  • Redis utilities: backend/open_webui/utils/redis.py
  • Session management: starsessions[redis]==2.2.1
  • Task coordination: backend/open_webui/tasks.py
  • Configuration sync: backend/open_webui/config.py:228-287
  • Rate limiting: backend/open_webui/utils/rate_limit.py

Security Best Practices

Redis Security:
  1. Authentication - Always use requirepass or ACLs
  2. TLS/SSL - Use rediss:// for encrypted connections
  3. Network Isolation - Bind Redis to private network only
  4. Firewall Rules - Restrict Redis port (6379) access
  5. Regular Updates - Keep Redis updated for security patches
  6. Memory Limits - Set maxmemory to prevent OOM

Next Steps

Build docs developers (and LLMs) love