DEV Community

Dipendra Neupane
Dipendra Neupane

Posted on

๐—ช๐—ต๐—ฎ๐˜ ๐˜„๐—ผ๐—ฟ๐—ธ๐˜€ ๐—ณ๐—ผ๐—ฟ ๐—ฆ๐—ถ๐—ด๐—ป๐—ฎ๐—น๐—ฅ ๐—น๐—ผ๐—ฐ๐—ฎ๐—น๐—น๐˜† ๐—ฐ๐—ฎ๐—ป ๐—ณ๐—ฎ๐—ถ๐—น ๐—ถ๐—ป ๐—ฝ๐—ฟ๐—ผ๐—ฑ๐˜‚๐—ฐ๐˜๐—ถ๐—ผ๐—ป

Here's what I've learned while taking SignalR web applications from local development to production.

โšก๐—”๐˜‚๐˜๐—ต ๐˜„๐—ผ๐—ฟ๐—ธ๐˜€ ๐—ฑ๐—ถ๐—ณ๐—ณ๐—ฒ๐—ฟ๐—ฒ๐—ป๐˜๐—น๐˜†.

Browsers don't let the client set the Authorization header on the WebSocket handshake, so the access token goes in the query string.

โšก๐—œ๐˜ ๐—ฐ๐—ฎ๐—ป ๐—ณ๐—ฎ๐—น๐—น ๐—ฏ๐—ฎ๐—ฐ๐—ธ ๐—ณ๐—ฟ๐—ผ๐—บ ๐—ช๐—ฒ๐—ฏ๐—ฆ๐—ผ๐—ฐ๐—ธ๐—ฒ๐˜๐˜€ ๐˜„๐—ถ๐˜๐—ต๐—ผ๐˜‚๐˜ ๐—ฏ๐—ฟ๐—ฒ๐—ฎ๐—ธ๐—ถ๐—ป๐—ด ๐˜†๐—ผ๐˜‚๐—ฟ ๐—ฎ๐—ฝ๐—ฝ.

Locally, you may be using WebSockets without realizing it. In production, a missing IIS WebSocket feature can prevent WebSockets from being used.

SignalR can then fall back to Server-Sent Events or Long Polling.

โšก๐—œ๐—ป๐—ฐ๐—ผ๐—บ๐—ถ๐—ป๐—ด ๐—บ๐—ฒ๐˜€๐˜€๐—ฎ๐—ด๐—ฒ๐˜€ ๐—ฎ๐—ฟ๐—ฒ ๐—น๐—ถ๐—บ๐—ถ๐˜๐—ฒ๐—ฑ ๐˜๐—ผ ๐Ÿฏ๐Ÿฎ ๐—ž๐—• ๐—ฏ๐˜† ๐—ฑ๐—ฒ๐—ณ๐—ฎ๐˜‚๐—น๐˜.

SignalR's maximum receive message size defaults to 32 KB for a single incoming hub message. If it exceeds this limit, SignalR throws an error, and the connection is closed.

You can increase the message size limit, but blindly increasing it will also increase memory usage.

โšก๐—œ๐˜ ๐˜„๐—ผ๐—ฟ๐—ธ๐˜€ ๐˜„๐—ถ๐˜๐—ต ๐—ผ๐—ป๐—ฒ ๐˜€๐—ฒ๐—ฟ๐˜ƒ๐—ฒ๐—ฟ, ๐˜๐—ต๐—ฒ๐—ป ๐—ฏ๐—ฟ๐—ฒ๐—ฎ๐—ธ๐˜€ ๐˜„๐—ต๐—ฒ๐—ป ๐˜†๐—ผ๐˜‚ ๐˜€๐—ฐ๐—ฎ๐—น๐—ฒ.

With multiple API instances, each SignalR connection belongs to a specific server. If another instance sends a message, it doesnโ€™t automatically know about the connections on the other servers.

If your SignalR server is running behind a load balancer, plan for cross-server message distribution using a backplane such as Redis or Azure SignalR Service.

The irony is, I switched to Ably after learning all of these hard lessons.

What's the hardest SignalR issue you've hit in production?

I share more engineering notes and production lessons on LinkedIn: Dipendra Neupane.

Top comments (1)

Collapse
 
koda2026 profile image
Harun - solo dev •

dipendra, this is a brutally accurate summary of the "works on my machine" signalr trap. the transition from single-node statefulness to distributed statelessness is exactly where real-time systems reveal their cracks.

your point about the 32kb default limit is a classic pain point. instead of blindly raising MaximumReceiveMessageSize (which opens the door to memory exhaustion attacks), a more resilient pattern for large payloads is to implement application-level chunking or switch to a blob storage reference (e.g., sending a presigned url via signalr, then letting the client download the payload via standard http).

regarding the redis backplane: when network partitions occur between nodes, how do you handle connection state reconciliation? do you rely purely on the client's automatic reconnect logic to re-establish the session, or do you implement a custom heartbeat/acknowledgment layer to ensure no messages are dropped during the failover window?

switching to a managed service like ably makes total sense to offload that operational complexity. fantastic, battle-tested breakdown. ๐Ÿฏโšก