Course contentsShow
← C#
Lesson 1448 of 1,90813. Real-time Communication with SignalRFree lesson

Managing Groups and Subscription Lifecycle

Add and remove clients from logical message groups for efficient targeted communication.

In this lesson, you will learn how to organize SignalR clients into logical groups to enable efficient, targeted messaging that scales beyond simple one-to-one or global broadcasting.

The Concept of Logical Groups

Broadcasting a message to every connected client is often inefficient and rarely what a real-world application requires. Instead, SignalR allows you to assign specific ConnectionIds to named groups—such as "ChatRoom_101" or "SupportQueue_NorthAmerica". When a message is sent to a group, only clients currently associated with that group receive the data.

Crucially, these groups are managed in the server's memory. When a client disconnects, they are automatically removed from all groups by the SignalR infrastructure, which simplifies the lifecycle management significantly. However, your application logic remains responsible for "subscribing" (adding) and "unsubscribing" (removing) users based on their interactions.

Implementation Patterns

To manage these subscriptions, you interact with the Groups property inside your Hub class. The most common pattern involves joining a group when a user performs an action (like entering a dashboard) and leaving it when that context is no longer relevant.

public class NotificationHub : Hub
{
    public async Task JoinDepartment(string departmentId)
    {
        // Add the current caller to the specified group
        await Groups.AddToGroupAsync(Context.ConnectionId, departmentId);
        
        await Clients.Group(departmentId).SendAsync("Notify", $"{Context.ConnectionId} joined.");
    }

    public async Task LeaveDepartment(string departmentId)
    {
        // Explicitly remove the caller when they leave the view
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, departmentId);
    }
}

Lifecycle Considerations

Because groups are transient and exist only in memory, they do not persist across server restarts. If your server instance restarts or scales out to multiple instances, you must ensure that your group state is handled consistently (typically by using a backplane like Redis).

Always pair your AddToGroupAsync calls with corresponding RemoveFromGroupAsync calls to prevent "stale" subscriptions. This ensures that users do not receive notifications for groups they are no longer actively participating in, maintaining both performance and data privacy.

Key Takeaway: Logical groups provide an efficient mechanism for targeted broadcasting, but you must manually manage the subscription lifecycle by explicitly adding and removing clients as their context changes.