System.Text.Json .NET 10

Server-Sent Events (SSE) offer a lightweight way to push data from server to client over a single HTTP connection.

SSE is ideal for dashboards, logs, telemetry, or notifications where you only need server-to-client streaming"not duplex messaging like WebSockets.

Why SSE?

  • Simple: Text-based via HTTP text/event-stream
  • Reliable: Built-in browser reconnection using Last-Event-ID
  • Efficient: Single long-lived request with low overhead
  • Great for: Status feeds, metrics, build logs, notifications

When not to use SSE:

  • Bidirectional messaging
  • Large binary payloads
  • High fan-out broadcast across many clients (consider SignalR)

In this exemple we will build a simple SSE endpoint that streams the current server time every second.

Building an SSE endpoint in .NET 10

First define a Minimal API SSE endpoint (HTTP/ASP.NET Core).

sseGroup.MapGet("/time", GetTimeStream)
    .WithName("GetTimeStream")
    .WithDescription("Streams current time every second");

Then implement the GetTimeStream method:

private static IResult GetTimeStream(CancellationToken cancellationToken)
{
    async IAsyncEnumerable<string> StreamTime(
        [EnumeratorCancellation] CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            yield return DateTime.UtcNow.ToString("HH:mm:ss.fff");
            await Task.Delay(1000, ct);
        }
    }

    return Results.ServerSentEvents(StreamTime(cancellationToken), eventType: "time-update");
}

This endpoint streams the current server time every second as SSE events with event type time-update.

It uses an async enumerable to yield time strings until the client disconnects.

The Results.ServerSentEvents helper formats the response correctly.

When the client connects, it will receive events as a continuous stream.

Consuming SSE in javaScript

function createConnection(name, url, handlers) {
    if (connections[name]) {
        connections[name].close();
        delete connections[name];
        updateStatus(name, 'disconnected');
        updateButton(name, 'Connect', 'primary');
        return null;
    }

    updateStatus(name, 'connecting');
    const eventSource = new EventSource(url);

    eventSource.onopen = () => {
        console.log(`${name} connected`);
        updateStatus(name, 'connected');
        updateButton(name, 'Disconnect', 'danger');
    };

    eventSource.onerror = (error) => {
        console.error(`${name} error:`, error);
        updateStatus(name, 'disconnected');
        updateButton(name, 'Connect', 'primary');
        delete connections[name];
    };

    Object.entries(handlers).forEach(([eventType, handler]) => {
        eventSource.addEventListener(eventType, handler);
    });

    connections[name] = eventSource;
    return eventSource;
}

This JavaScript function creates an SSE connection using the EventSource API.

It handles connection open, error events, and allows registering custom event handlers for specific SSE event types.

It also manages connection state and UI updates.

You can use it like this:

createConnection('time', '/sse/time', {
'time-update': (event) => {
    document.getElementById('time-display').textContent = event.data;
}
});

This connects to the /sse/time endpoint and updates the #time-display element with the received time every second.

At this point you have a fully working SSE server and client.

With some css and html you can create a simple dashboard to display the time updates in real-time.

Performance Considerations

SSE in .NET 10 is built on top of System.Net.ServerSentEvents and is highly optimized:

  • Memory efficient: Uses streaming with backpressure support
  • Scales well: Leverages async I/O and doesn't block threads
  • JSON optimized: Uses System.Text.Json for serialization
  • HTTP/2 friendly: Multiple SSE streams can share a single connection

Conclusion

The new SSE support in .NET 10 brings a powerful, standards-based real-time communication option to ASP.NET Core. With its simple API, automatic serialization, and native support in both Minimal APIs and MVC, it's never been easier to add live updates to your applications.

Whether you're building a live dashboard, notification system, or activity feed, SSE in .NET 10 provides a clean, efficient solution that's easy to implement and maintain.

Additional Resources