Skip to main content

Command Palette

Search for a command to run...

ASP.NET Core SignalR Interview Questions for Senior .NET Developers (2026)

Updated
โ€ข13 min read

ASP.NET Core SignalR is one of those topics that separates candidates who have built real-time features in production from those who have only read the docs. The questions interviewers ask about SignalR go well beyond "what is a Hub" โ€” they probe your understanding of transport negotiation, connection lifecycle management, scaling across server instances, group messaging, and the trade-offs between SignalR and alternative real-time technologies. If you are preparing for a senior .NET role where real-time communication is part of the architecture, this guide covers the full range of questions you are likely to encounter. The complete working patterns โ€” with annotated source code for production-grade SignalR scenarios โ€” are available on Patreon, ready to run and adapt for your own projects.

If you want to see how ASP.NET Core SignalR has evolved recently, the What's New in ASP.NET Core 10 SignalR article is a good companion โ€” it covers the specific improvements in .NET 10 that are increasingly showing up in 2026 interviews.

The questions below are grouped by difficulty: Basic โ†’ Intermediate โ†’ Advanced. Each question includes the key points a strong candidate is expected to cover.


Basic Questions

What Is ASP.NET Core SignalR and When Should You Use It?

ASP.NET Core SignalR is a library that simplifies adding real-time web functionality to applications. It enables server-to-client push communication โ€” meaning the server can send data to connected clients at any time, without clients polling for it.

You should reach for SignalR when your application requires live push notifications, collaborative editing, real-time dashboards, chat functionality, or any scenario where server-initiated updates are necessary. If the communication pattern is strictly request/response, SignalR is unnecessary overhead and a standard REST or gRPC endpoint is the right tool.

What Is a SignalR Hub?

A Hub is the central abstraction in ASP.NET Core SignalR. It is the server-side class clients connect to and through which all communication flows. Hubs expose methods that clients can call (similar to RPC), and they provide a built-in proxy through which the server can invoke methods on connected clients.

A strong answer includes: Hub is transient per-invocation, so you should not store state in Hub instance fields. Use IHubContext<T> when you need to send messages from outside the Hub class (e.g., from a controller or background service).

What Transport Protocols Does SignalR Support?

SignalR supports three transports, selected via negotiation in order of preference:

  1. WebSockets โ€” the preferred transport; full-duplex, lowest latency
  2. Server-Sent Events (SSE) โ€” server-to-client only; works over HTTP/1.1
  3. Long Polling โ€” fallback for environments where neither WebSocket nor SSE is available

The negotiation process is automatic. SignalR will select the best transport supported by both the client and the server environment. You can restrict or force specific transports if required.

What Is the Difference Between Clients.All, Clients.Caller, and Clients.Others?

These are built-in properties on the Hub base class that provide different targeting scopes for sending messages:

  • Clients.All โ€” sends a message to every connected client
  • Clients.Caller โ€” sends a message only to the client that invoked the current Hub method
  • Clients.Others โ€” sends to all connected clients except the caller
  • Clients.Client(connectionId) โ€” sends to a specific client by its connection ID
  • Clients.Group(groupName) โ€” sends to all clients in a named group

What Is a SignalR Connection ID?

Every client that connects to a SignalR Hub is assigned a unique, server-generated ConnectionId string. It identifies a single connection for the lifetime of that connection. If a client disconnects and reconnects, it receives a new ConnectionId.

ConnectionId is accessible inside Hub methods via Context.ConnectionId. It is used for targeted messaging, but should not be used as a stable user identifier โ€” map ConnectionId to authenticated user identities when you need to send messages to a specific user across multiple connections.


Intermediate Questions

How Do SignalR Groups Work and What Are Their Limitations?

Groups are named collections of connections. Any Hub method can add or remove a connection from a group using Groups.AddToGroupAsync and Groups.RemoveFromGroupAsync. You can then broadcast to all group members with Clients.Group(groupName).

Key limitations interviewers probe:

  • Groups are not persistent โ€” if a client disconnects, it is automatically removed from all groups. The application must re-add users to groups after reconnection.
  • Groups have no built-in membership query โ€” you cannot ask "who is in this group?" from the Hub. You must track membership yourself in a store such as a distributed cache or database.
  • Groups span scale-out only with a backplane โ€” without a backplane (e.g., Redis), a message sent to a group on Server A will not reach clients connected to Server B.

How Do You Scale ASP.NET Core SignalR Across Multiple Servers?

By default, SignalR uses in-memory state โ€” each server only knows about its own connections. When you run multiple instances behind a load balancer, a client connected to Server A cannot receive a message sent on Server B.

The solution is a backplane: a shared message broker that all servers subscribe to. When one server sends a message, it publishes it to the backplane; all other servers receive and deliver it to their local clients.

Common backplanes:

  • Redis โ€” the standard choice; uses Microsoft.AspNetCore.SignalR.StackExchangeRedis
  • Azure SignalR Service โ€” Microsoft's fully managed backplane that offloads connection handling entirely
  • SQL Server โ€” available but rarely used in high-throughput scenarios due to latency

A senior candidate should also mention sticky sessions (affinity routing) as an alternative for simpler setups, and explain why it is not sufficient for true fault-tolerant scale-out.

How Does SignalR Handle Reconnection?

Client-side reconnection behavior depends on the client library and configuration:

  • Automatic reconnect (recommended): The JavaScript client and the .NET client both support .withAutomaticReconnect() during connection builder configuration. By default it retries at 0, 2, 10, and 30 seconds. You can provide a custom retry policy.
  • State recovery: When a client reconnects, it gets a new ConnectionId. Any group memberships, in-flight messages, and caller-specific state from the previous connection are lost unless the application rebuilds them.
  • Stateless design principle: Because reconnection resets connection state, production applications should design for idempotent reconnection โ€” re-join groups on reconnect, re-fetch any missed state from the server.

What Is the Difference Between SendAsync and InvokeAsync in the SignalR .NET Client?

  • SendAsync โ€” fire-and-forget. Sends the invocation to the server and does not wait for a return value. Returns Task (completes when the message is sent, not when the server handles it).
  • InvokeAsync<T> โ€” sends the invocation and awaits a return value from the server-side Hub method. The Hub method must return a typed value, and the client call must match that type.

For read-heavy or result-driven operations, InvokeAsync is appropriate. For broadcast or notification-style calls where you do not need a confirmation, SendAsync is preferred for lower overhead.

How Do You Send Messages to a Specific User (Not Just a Connection)?

SignalR provides Clients.User(userId) for sending to all connections associated with an authenticated user. This works through the IUserIdProvider interface, which by default resolves the user ID from ClaimTypes.NameIdentifier.

You can customize user ID resolution by implementing IUserIdProvider and registering it in DI. For example, you might resolve by email, tenant-scoped ID, or a custom claim.

Important detail: a single user can have multiple active connections (same user, different browser tabs). Clients.User(userId) sends to all of them simultaneously.

How Do You Send SignalR Messages from Outside a Hub (e.g., from a Controller or Background Service)?

Inject IHubContext<THub> into the controller or service. This gives you access to Clients and Groups without being inside a Hub invocation. It is the correct pattern for proactive server-initiated pushes, such as a background job completing and notifying clients, or a webhook arriving and broadcasting an update.

IHubContext<THub> does not give you Context (which is per-connection). It is purely for outbound message delivery.


Advanced Questions

How Would You Implement Authorization in SignalR Hubs?

Hub methods and Hub connections can be protected at multiple levels:

  1. Connection-level authorization: Apply [Authorize] to the Hub class itself. Unauthenticated clients are rejected during the negotiation/connection phase.
  2. Method-level authorization: Apply [Authorize] or [Authorize(Roles = "...")] to individual Hub methods for fine-grained control.
  3. Policy-based authorization: Inject IAuthorizationService into the Hub and call AuthorizeAsync inside the Hub method with a resource-based policy.

For JWT-based APIs, the access token must be passed differently because browsers cannot set authorization headers for WebSocket connections. The JavaScript SignalR client sends the token as a query string parameter (access_token). On the server, you configure OnMessageReceived in the JWT options to read the token from the query string โ€” a detail interviewers specifically check.

What Are the Performance and Scalability Considerations for High-Concurrency SignalR Applications?

Key areas a senior candidate should cover:

  • Thread and connection model: SignalR Hub method invocations are not run in parallel by default per-connection. A single client's Hub calls are serialized. Use [EnableConcurrentExecution] (available in recent versions) if you need parallel execution per connection, but handle races yourself.
  • Message size: Large messages block the connection. Use streaming (IAsyncEnumerable<T> or ChannelReader<T>) for data that is large or emitted incrementally โ€” financial ticks, log streams, progress updates.
  • Connection limits: Each persistent WebSocket connection consumes a file descriptor and memory. Plan connection limits at the OS and Kestrel level. Azure SignalR Service offloads this concern entirely.
  • Avoid Hub for polling patterns: If a client calls a Hub method on a timer to "check for updates," that is polling, not real-time. Redesign so the server pushes when data changes.
  • Backpressure: If clients are slow consumers, message queues can back up. Monitor HubCallerContext and consider client-side acknowledgement patterns for high-throughput scenarios.

How Does SignalR Streaming Work and When Should You Use It?

SignalR supports two streaming patterns:

Server-to-client streaming: The Hub method returns IAsyncEnumerable<T> or ChannelReader<T>. The client subscribes and receives items as they are produced, rather than waiting for a complete response. Ideal for live data feeds, progress reporting, or paginated large datasets.

Client-to-server streaming: The client sends a stream of items to the Hub method (using IAsyncEnumerable<T> as the Hub method parameter). The Hub processes items as they arrive. Useful for chunked file uploads, live telemetry ingestion, or typed event streams.

The key advantage over single-value responses is backpressure alignment โ€” neither side has to buffer the entire payload. Senior candidates should know that ChannelReader<T> gives manual control over the producer side, useful when the data source is not natively async-enumerable.

What Is the Difference Between ASP.NET Core SignalR and Azure SignalR Service?

ASP.NET Core SignalR (Self-Hosted)Azure SignalR Service
Connection handlingManaged by your serversOffloaded to Azure
Scale-outRequires Redis/backplaneBuilt-in, serverless-compatible
Connection limitBounded by server resourcesUp to millions of concurrent connections
Operational overheadHigh (infra, backplane, Redis)Low (fully managed)
Cost modelInfrastructure costPer-connection/message pricing
Negotiation URLYour serverAzure endpoint with token redirect

For small-scale or on-premises applications, self-hosted is simpler. For cloud applications expecting thousands of concurrent users, Azure SignalR Service eliminates the backplane problem and the connection-per-server limit entirely.

How Do You Test SignalR Hubs?

Testing SignalR Hubs requires a different approach from standard controller tests:

  • Unit testing Hub methods: Instantiate the Hub directly, mock IHubCallerClients, IGroupManager, and HubCallerContext using Moq or NSubstitute. Call the Hub method and assert the expected SendAsync calls were made on the mock.
  • Integration testing: Use WebApplicationFactory to spin up the full ASP.NET Core host, then connect using the SignalR .NET client in tests. This validates the full pipeline including middleware, authentication, and routing.
  • Testing IHubContext<T>: Inject it as you would in production, mock it in unit tests for services that use it.

A common interview question is to describe how you would assert that a Hub method broadcast to the correct group with the right payload โ€” the answer involves capturing the SendAsync call on the mocked IGroupManager.Clients.Group(...) proxy.

What Is Sticky Session (Server Affinity) and When Is It Relevant for SignalR?

Sticky sessions (or affinity routing) ensure that all requests from a specific client are routed to the same backend server. For SignalR, this matters because:

  • The negotiation handshake and the WebSocket connection must reach the same server instance
  • Without affinity and without a backplane, a client negotiating on Server A but WebSocket-connecting to Server B will fail

Sticky sessions solve the negotiation/WebSocket mismatch problem, but they do not solve the broadcast problem โ€” messages sent on Server A still do not reach clients on Server B. For production multi-server deployments, a backplane is still required for full message fan-out. Sticky sessions can supplement a backplane setup (to reduce backplane load) but are not a replacement.


Quick Reference: Key Concepts to Nail in Any SignalR Interview

ConceptWhat Interviewers Want to Hear
Hub lifecycleTransient per invocation; don't store state in fields
ConnectionIdResets on reconnect; map to user identity for persistence
GroupsNot persistent; must re-add after reconnect; need backplane to span servers
Scale-outRedis backplane or Azure SignalR Service
Auth for WebSocketsToken via query string; read in OnMessageReceived
StreamingIAsyncEnumerable<T> / ChannelReader<T> for incremental data
IHubContextFor outbound push from outside Hub; inject it anywhere
TestingMock IHubCallerClients; integration test with the .NET client

If you are preparing for architecture-level interviews that also cover gRPC as an alternative transport, the ASP.NET Core gRPC Interview Questions article covers the questions interviewers use to probe gRPC knowledge for senior candidates.


โ˜• Prefer a one-time tip? Buy us a coffee โ€” every bit helps keep the content coming!


Frequently Asked Questions

What level of SignalR knowledge is expected for a senior .NET developer interview?

Senior-level interviews expect you to go well beyond basic Hub setup. You should be able to explain transport negotiation, justify when to use SignalR versus alternatives like gRPC or SSE directly, describe scale-out strategies with Redis or Azure SignalR Service, and discuss production concerns such as authentication, reconnection handling, group lifecycle management, and performance at scale.

Is ASP.NET Core SignalR still relevant in 2026 with HTTP/3 and gRPC available?

Yes. SignalR remains the standard for browser-facing real-time scenarios because it handles transport negotiation automatically, works across diverse client environments (browsers, mobile, desktop), and integrates directly with ASP.NET Core authentication and authorization. gRPC is preferred for service-to-service communication. SignalR and gRPC are complementary, not competing choices.

How should I handle authentication tokens with SignalR WebSocket connections?

Browsers do not support custom headers for WebSocket connections. The standard approach for JWT authentication with SignalR is to pass the access token as a query string parameter (?access_token=...), which the JavaScript SignalR client does automatically when you configure the accessTokenFactory. On the server, you configure the JWT bearer handler's OnMessageReceived event to read the token from the query string. This is a detail interviewers specifically probe in senior interviews.

What is the right way to send messages from a background service to SignalR clients?

Inject IHubContext<THub> into the background service using the IServiceScopeFactory pattern (since Hubs are scoped and background services are singletons). Call Clients.All.SendAsync(...) or target groups and users as needed. Never instantiate a Hub directly or call Hub methods from outside the SignalR pipeline.

What happens to group memberships when a SignalR client disconnects?

Group memberships are not persistent. When a client disconnects โ€” whether normally or due to network failure โ€” it is automatically removed from all groups it had joined. Your application is responsible for re-adding the user to the appropriate groups when they reconnect. This is typically done by overriding OnConnectedAsync in the Hub and restoring group membership from your application's state (e.g., a cache or database record of which groups the user belongs to).

How many concurrent connections can a self-hosted ASP.NET Core SignalR server handle?

The practical limit depends on hardware and connection type, but a single server can typically support 5,000โ€“20,000 concurrent WebSocket connections before memory and file descriptor limits become the constraint. For higher concurrency, Azure SignalR Service removes this ceiling by offloading connection management entirely. For on-premises deployments, a Redis backplane with multiple server instances distributes the load.

When should I use SignalR streaming instead of regular Hub method calls?

Use streaming when: the total data volume is too large to buffer in a single response, data is generated incrementally over time (progress updates, financial ticks, sensor readings), or you want to begin delivering results to the client before the full dataset is available. For standard request/response where the server computes a result and returns it immediately, a regular Hub method or a REST endpoint is simpler and equally appropriate.