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)
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. ๐ฏโก