myagent.mxBLOG

apis & sending · sse vs websockets

One day spike: 4 metrics to pick SSE or WebSockets for developers

Developer checklist to pick SSE or WebSockets. Run a one day spike and log four metrics: connections, memory, reconnect rate, latency. Consider Sendmux...

11 min read~3,385 tokensMarkdown
Four spike metrics score SSE against WebSocket on a one-day decision card

For most server-to-client features, like live dashboards, notifications or AI token streaming, Server-Sent Events (SSE) is the simpler, more scalable choice. Reach for WebSockets when your application needs true two-way traffic, binary payloads or client messages at the same frequency as server pushes. The exceptions that push you toward WebSockets even for “mostly read” features: binary-heavy streams and interactive agent control that needs instant round trips.


TL;DR

5 takeaways
  1. SSE is ideal for mostly server-driven features like live dashboards and notifications, and scales well with HTTP/2 multiplexing.
  2. WebSockets support binary data, two-way communication, and continuous client-server interaction, making them suitable for chat or real-time control systems.
  3. WebSockets typically require more server resources, sticky sessions, or pub/sub systems, while SSE uses standard HTTP infrastructure for scalability.
  4. For features with occasional client actions, pairing SSE with simple HTTP POST requests is simpler and cheaper than using WebSockets.
  5. Testing connection stability, memory use, and latency during a short spike helps determine whether SSE or WebSockets better fit your infrastructure.

Protocol fundamentals: EventSource versus WebSocket

SSE runs over plain HTTP. A client opens a connection with the EventSource API, the server responds with a text/event-stream content type, and it pushes newline-delimited text events down that single, long-lived response. The WHATWG HTML Standard defines this format along with built-in reconnection and Last-Event-ID resume, so a dropped connection can pick up where it left off without extra application code.

WebSocket works differently from the first handshake. A client sends an HTTP request with an Upgrade header, and once the server agrees, the connection stops being HTTP and becomes a persistent, full-duplex TCP channel. RFC 6455 specifies that handshake and the binary framing that follows, which is why WebSocket supports both text and binary payloads while SSE stays text-only.

A few things worth knowing before you pick either one:

  • SSE payloads are text only; WebSocket frames carry text or binary data.
  • Browsers limit concurrent HTTP/1.1 connections per origin, affecting SSE under that protocol version.
  • HTTP/2 multiplexing removes most of that per-origin limit, letting SSE scale more comfortably on modern stacks.
  • Both have solid browser support documented on MDN’s Server-sent events page.

When SSE fits your product

SSE suits any feature where the server is the one doing the talking: live dashboards, activity feeds, push notifications, AI token streaming, or a mailbox event stream that tells an agent new mail has arrived. The appeal is less about the protocol itself and more about what you don’t have to build.

  • Automatic reconnection and Last-Event-ID resume come free with the EventSource API.
  • SSE rides on standard HTTP, so it scales through familiar reverse proxies, load balancers and CDNs without special handling.
  • Connections stay comparatively cheap to hold open compared with a full-duplex socket.
  • Under HTTP/1.1, browsers limit concurrent connections per origin for SSE; HTTP/2 multiplexing is what makes SSE scale elegantly for many apps today, according to the Websocket.

The constraint is directionality: SSE only pushes from server to client, carries text, and isn’t built for frequent client-to-server chatter. When your feature needs the occasional action from the client, like dismissing a notification or triggering a refresh, pair the SSE stream with a plain HTTP POST or REST call instead of forcing it through the stream.

Pro Tip: Treat SSE as a read channel and keep writes on ordinary HTTP endpoints. It’s far less code than building bidirectional logic into a stream that was never designed for it.

An SSE stream pushes events down while a separate HTTP POST carries occasional writes back

When WebSockets earn their complexity

WebSockets make sense when the client needs to send at roughly the same cadence it receives, or when the payload itself demands binary framing. Chat applications, multiplayer games, collaborative editors, live binary data feeds and interactive agent control systems all fit this shape, because both sides are talking continuously and latency on each leg matters.

  • Binary frames support audio, video chunks and compact serialised data without a text-encoding tax.
  • A single connection carries simultaneous send and receive, which lowers header overhead for genuinely symmetric traffic.
  • You take on reconnection logic and state resynchronisation yourself. Unlike SSE, nothing in RFC 6455 hands you that for free.
  • Fan-out at scale often needs sticky sessions or an external pub/sub layer, and each open socket tends to hold more server-side state than an SSE connection.

Because so much of the reliability work sits outside the protocol itself, it’s worth leaning on a proven library or a managed real-time platform rather than hand-rolling reconnection and resync from scratch, particularly if your team hasn’t operated WebSocket infrastructure at scale before.

Performance and scalability trade-offs

The two transports put different pressure on your infrastructure, and the differences show up well before you hit real scale.

WebSocket connections typically hold more state per connection: frame buffers, protocol bookkeeping and often session data tied to a specific server instance. That pushes you toward sticky sessions, which bind a client to one backend process, or an external pub/sub system like Redis to fan events out across instances. SSE avoids most of this because it’s stateless HTTP underneath, which fits naturally into existing load balancer and CDN patterns.

  • Per-connection memory: WebSockets generally cost more per open connection than SSE.
  • Fan-out: WebSocket fan-out usually needs sticky sessions or pub/sub; SSE scales through ordinary HTTP infrastructure.
  • HTTP/2: multiplexing lifts SSE past the per-origin connection caps that apply under HTTP/1.1, per the WHATWG spec.
  • Network path: WebSocket uses wss:// over TLS, SSE rides ordinary https://, and some corporate proxies and firewalls are more permissive with plain HTTP streaming than with persistent socket upgrades.

CDN support for long-lived streaming connections varies by provider on both sides, so test your specific stack rather than assuming either transport passes through cleanly.

A decision checklist for picking a transport

Start with one question: does the client need to send data at roughly the same cadence it receives it? If yes, favour WebSocket. If no, SSE plus a plain HTTP POST for occasional client actions is usually the simpler, cheaper build, a heuristic echoed in Vercel’s engineering guidance.

Work through the rest of the checklist once you’ve answered that:

  1. Do you need binary payloads, like audio or compact serialised data? That points to WebSocket.
  2. How often does the client need to send messages, and does that frequency match the server’s push rate?
  3. What’s your expected concurrent connection count, and have you sized server memory for it?
  4. Do your users sit behind enterprise proxies or firewalls that might block socket upgrades?
  5. Are you prepared to build and test reconnection and state resync, or would a managed provider save real engineering time?

Run a short spike before committing. Measure connections sustained per instance, memory and CPU under load, reconnect rate after a simulated network drop, and end-to-end latency from server event to client render.

Pro Tip: A one-day spike that logs these four numbers will tell you more than any architecture debate. Numbers settle arguments that opinions don’t.

Map the result to an architecture: SSE plus HTTP POST for read-heavy features, WebSocket for symmetric real-time traffic, a hybrid when a single feature genuinely needs both shapes, or a managed provider when your team would rather not operate either transport directly.

Hybrid and fallback patterns worth knowing

Plenty of production systems run SSE and WebSockets side by side rather than picking one everywhere. A live feed might ride SSE while an adjacent interactive control panel, say for remotely signalling an agent or device, uses a WebSocket for the low-latency path, a split visible in production in Genesis Engine’s changelog, which records a real-time SSE event system that holds a connection open to deliver notifications as they land.

  • Use SSE plus HTTP POST when the client occasionally acts but mostly listens.
  • Add WebSocket only for the subset of features that need genuine two-way, low-latency exchange.
  • Fallback chains, WebSocket to HTTP streaming to long polling, exist for exactly the proxy and firewall cases where a direct socket upgrade fails.
  • Hybrids cost more to maintain, so reserve them for feature sets that truly need both transport shapes rather than defaulting to both out of caution.

Our take: default to the simpler transport

Default to SSE wherever the feature is server-push-only, and reach for WebSocket only once bidirectionality or binary data genuinely require it. Most teams overbuild here, adding socket infrastructure for features that never needed a two-way channel.

If your team doesn’t have the bandwidth to build solid reconnection logic and observability, a managed provider is the pragmatic shortcut, and that’s exactly the gap our own mailbox event stream was built to close.

How we handle real-time delivery for agent inboxes

We built Sendmux so agent mailboxes stay persistent rather than disappearing between webhook drops. Inbound mail reaches an agent through a Server-Sent Events stream at the mailbox events endpoint, for agents that can’t host a public callback, or through signed webhooks for backends that can, with HMAC-SHA256 signatures and retry with backoff built in.

Every mailbox comes with scoped tokens, SDKs in multiple languages, and a free starting tier. An agent can discover and self-register a mailbox at Myagent in one session, with no card and no human in the loop, then invite a human owner once it’s ready to send.

A mailbox event stream reaches an agent over SSE while signed webhooks reach its backend

FAQ

Is SSE based on HTTP?

Yes. SSE runs over standard HTTP using the text/event-stream content type, with the browser’s EventSource API handling the connection, reconnection and Last-Event-ID resume, as defined in the WHATWG HTML Standard. It needs no special protocol upgrade the way WebSocket does.

Does ChatGPT use SSE or WebSockets?

Token streaming in large language model products commonly uses server-to-client streaming approaches like SSE or HTTP streaming, since the server is the one producing content and the client mostly listens, according to engineering coverage of streaming patterns. WebSocket tends to appear instead when a product needs interactive, bidirectional signalling rather than one-way token delivery.

What is WSS versus HTTPS?

wss:// is the WebSocket protocol running over a TLS-encrypted connection, the secure counterpart to plain ws://, specified as part of the handshake behaviour in RFC 6455. https:// is standard HTTP over TLS and is what SSE uses, since SSE is an HTTP mechanism rather than a separate protocol.

What are the different types of WebSocket connections?

WebSocket connections are typically described by payload type: text frames for JSON or plain messages and binary frames for audio, video chunks or compact serialised data, both covered under the one RFC 6455 specification. Beyond frame type, the distinction that matters operationally is whether a connection is managed directly or routed through a provider with automatic fallback to HTTP streaming or long polling.

Can I use SSE instead of webhooks?

SSE and webhooks solve different delivery problems: SSE keeps a live connection open so a client receives events as they happen, while a webhook pushes an event to a server endpoint you host. For mailbox events specifically, we support both an SSE stream and signed webhooks, so you can pick whichever fits whether your agent can host a public endpoint.

Sources

Give an agent its own address

Sendmux is the Email Inbox API for AI Agents.

Explore Sendmux