SignalR with a Redis backplane
Neos uses SignalR to deliver real-time notifications to browser sessions in a Kubernetes namespace. The notifications hub is instantiated inside each backend replica of a Neos cluster. When the backend is scaled out, Redis acts as the SignalR backplane so every hub instance can exchange messages with the others.
This article explains the deployment model used by Neos in Kubernetes and how the Redis backplane fits into it.
Note
The Redis backplane is a live message propagation layer, not a durable queue. It forwards notifications between active SignalR hub instances, but it does not store them for later delivery.
Deployment model
In a typical namespace, the relevant pieces are:
- the ingress controller, which receives browser traffic
- the gateway, which routes requests and keeps the notification path sticky
- the backend replicas, which host the notifications hub inside each pod
- the Redis instance used by SignalR, usually
redisSignalR
The notifications hub runs once in every backend replica. Each backend replica maintains its own client connections, while Redis keeps the replicas in sync.
flowchart LR
Browser[Browser] --> Ingress[Ingress]
Ingress --> Gateway[Gateway]
Gateway --> BackendA[Backend replica A\nNotifications hub + app]
Gateway --> BackendB[Backend replica B\nNotifications hub + app]
BackendA <--> Redis[(Redis backplane\nredisSignalR)]
BackendB <--> Redis
BackendA --> ClientA[Connected clients]
BackendB --> ClientB[Connected clients]
Request and notification flow
- The browser opens a SignalR connection through the ingress and gateway.
- Sticky sessions keep the browser connected to the same backend replica for the lifetime of the websocket connection.
- The backend replica hosts the local SignalR hub instance and the client connection stays attached to that replica.
- A server-side component sends a notification through the local hub instance.
- The hub instance publishes the message to Redis.
- Redis forwards the message to every subscribed backend replica in the namespace.
- Each backend replica pushes the notification to its own connected clients.
sequenceDiagram
participant B as Browser
participant G as Gateway
participant B1 as Backend replica A\nNotifications hub
participant B2 as Backend replica B\nNotifications hub
participant R as Redis backplane
B->>G: Connect / negotiate SignalR
G->>B1: Route to a backend replica
B1-->>B: WebSocket established
B2->>R: Publish notification
R-->>B1: Fan out message
R-->>B2: Fan out message
B1-->>B: Push notification to the client
Why Redis is needed
Without a backplane, each backend replica would only know about the clients connected to itself. That works for a single replica, but it breaks down as soon as the backend is scaled out.
Redis solves this by providing a shared pub/sub channel between backend replicas:
- any replica can publish a notification
- every replica receives the message
- each replica delivers the message to its own active connections
This allows the notifications hub to scale horizontally while preserving real-time delivery across the whole namespace.
Kubernetes and Helm settings
Neos Helm charts expose a dedicated Redis instance for SignalR notifications:
redisSignalRdeploys or references the Redis store used by the notifications hub- the Redis database number used for SignalR is isolated from the other Neos Redis usages
notificationsHub.strategycontrols the deployment strategy of the notifications hub
See Helm configuration for the full configuration surface.
For routing behavior, especially sticky sessions on the ingress and the gateway path, see Gateway routing, CORS, and unavailable tenants settings.
Operational notes
- Keep the ingress and gateway affinity settings enabled for notification routes.
- Use the dedicated
redisSignalRinstance when you want to isolate SignalR traffic from other Redis workloads. - Remember that Redis backplane traffic is transient; it is not meant for replay or offline delivery.