SignalR for your notifications? You may not need it
Real time = SignalR. That's the reflex. Except that 80% of the time, you just want to send data from the server to the client. Nothing else.
Notifications, dashboards, progress bars, activity feeds... it's all server-to-client push. And the client? The rest of the time, it calls your REST API to act. Like it always has.
The real need for bidirectional is: chat, multiplayer games, collaborative whiteboards... cases where the client talks as much as the server.
The native answer: Server-Sent Events
If you only need to push real-time info from back to front, look at Server-Sent Events (SSE). It's native, lightweight, and does exactly that: server-to-client push. And .NET 10 makes the server-side implementation even simpler.
On the back end, it's standard HTTP: one connection that stays open. Your business actions push typed events onto it, async, without blocking a thread:
// A minimal SSE endpoint
app.MapGet("/notifications", async (HttpContext ctx, CancellationToken ct) =>
{
ctx.Response.Headers.ContentType = "text/event-stream";
await foreach (var notif in queue.ReadAllAsync(ct))
{
await ctx.Response.WriteAsync($"event: {notif.Type}\ndata: {notif.Json}\n\n", ct);
await ctx.Response.Body.FlushAsync(ct);
}
});
On the front, EventSource is native in every modern browser, zero library to install. The front connects once, receives, checks the type, reacts:
const source = new EventSource('/notifications');
source.addEventListener('order', e => refresh(JSON.parse(e.data)));
To put it simply: it's like installing a doorbell. The delivery person rings, drops the parcel and leaves. You're not stuck behind the door waiting, and you know right away when you've been delivered.
SignalR / SSE: the comparison
SignalR gives you: bidirectional by default, a mandatory front-end lib, auto fallback (WebSocket, SSE, Long Polling), native mobile clients, group management.
SSE gives you: unidirectional (server to client), zero lib, native browser reconnection, readable HTTP in your devtools.
The trade-off: SSE is web only. No native EventSource on iOS, Android, React Native or Flutter: third-party libs required. SignalR ships clients for all those platforms.
What about scaling?
SignalR needs a backplane (Redis, Azure SignalR Service...) so your instances can talk. SSE has the same "problem". But nothing stops you from plugging in your own pub/sub (Redis, RabbitMQ...).
My experience
Personally, I used SignalR by default. Until I worked on a queue-management system for a football stadium entrance: pushing positions in real time to screens, with zero need for the client to reply. SSE did the job, without the complexity.
Takeaway: SSE doesn't replace SignalR. It's just that you don't always need a tank to go get bread.
This article comes from one of my LinkedIn posts (in French): join the discussion ↗