Engineering

The WebSocket Client We Wanted Applications to Have

Eric Brasher August 6, 2026 at 2:15 PM 5 min read

A good protocol can still create bad application code if every team must rebuild ticket acquisition, frame correlation, reconnect jitter, sequence checkpoints, and cancellation. This afternoon we packaged those responsibilities into FabrCore.Client.WebSocket.

One Client Owns the Connection Lifecycle

FabrCoreWebSocketClient receives an authenticated HttpClient, a Host URI, and a stable client id. It requests a fresh ticket for every connection, negotiates v2, waits for hello, and reconnects with exponential backoff and jitter capped at 30 seconds.

The caller supplies cancellation and decides when the client is disposed. Temporary failures do not require page code to construct a new socket, while non-retryable protocol or authorization errors surface as typed exceptions with a code and retryability flag.

Methods Match Application Intent

Instead of serializing operation envelopes by hand, applications call methods such as SendMessageAndReceiveAsync, SendEventAsync, GetAgentHealthAsync, GetTrackedAgentsAsync, and GetSharedAgentsAsync. Correlation ids and accepted responses stay inside the transport implementation.

Ordered principal deliveries are exposed through ReadDeliveriesAsync. After the application has committed a delivery to its local state, it calls AcknowledgeAsync. A checkpoint-store interface lets desktop, server, and mobile applications choose the durability appropriate to their environment.

Migration Gets Smaller

Existing v1 consumers still have a breaking wire migration, but they do not have to become protocol experts. Replace the old raw connection code with the package, map each action to a typed method, choose a stable client id, and implement the delivery loop plus gap resynchronization.

Blazor Server applications can keep the client in a scoped application service. Native services can register it for the lifetime of a principal session. Browser-only applications can implement the documented v2 frames directly while retaining their existing authentication stack.

Complete example

See Connect, receive, and acknowledge in the WebSocket guide.