Scaling SignalR for Blazor Server

Sticky sessions, backplanes, connection budgets and the load test that tells you which one you actually need.
The scale-out question
Blazor Server keeps one long-lived connection per open tab. That single fact drives every scaling decision you will make.

Sticky sessions come first
A circuit lives on exactly one server. If your load balancer moves a client mid-session, the circuit is gone. Turn on session affinity before you tune anything else.
# Azure Container Apps
ingress:
stickySessions:
affinity: sticky
Do you need a backplane?
A Redis backplane distributes SignalR hub messages between servers. Blazor Server circuits are not shared between servers, so a backplane does not let a circuit roam. You need one when you push server-initiated updates to clients that may be connected anywhere:
- Live dashboards fed by a background service
- Notification fan-out
- Presence and typing indicators
If none of those apply, skip it.
Budgeting connections
| Concurrent tabs | Memory per circuit | Rough server memory |
|---|---|---|
| 500 | 250 KB | ~125 MB |
| 2 000 | 250 KB | ~500 MB |
| 10 000 | 250 KB | ~2.5 GB |
Measure your own number with dotnet-counters; 250 KB is a starting guess, not
a promise.
Load test with real browsers, not with a script that opens sockets. The render tree diff is the expensive part, and only a real client produces it.
Part four covers the telemetry that makes all of this visible.
More Posts
Comments (1)
The point about backplanes not letting circuits roam is the thing everyone gets wrong. We added Redis and were baffled that failover still dropped sessions.
Leave a comment
No account needed — just your name and email.