DEV Community

Vivian Voss
Vivian Voss

Posted on • Originally published at vivianvoss.net

Server-Sent Events

Stack Patterns — Episode 09

Last episode built a WebSocket. Full duplex. Both sides talk. Splendid for chat. Rather generous for a notification badge.

Most real-time features are one-way: the server knows something changed, the client needs to hear about it. Dashboards, feeds, build logs, stock tickers. The client never sends. It listens.

The browser solved this in 2015 with one line of JavaScript that nobody teaches.

The Client

const source = new EventSource('/events');
source.onmessage = e =>
  document.querySelector('#feed').textContent = e.data;
Enter fullscreen mode Exit fullscreen mode

One line to connect. One line to handle. No npm. No cleanup. No reconnect logic. EventSource reconnects automatically. The browser handles it. You do not.

WebSocket requires an onclose handler, a backoff timer, and state reconciliation after reconnect. EventSource requires nothing. It simply reconnects and resumes. The specification demands it.

The Server

Rust (axum):

async fn events() -> Sse<impl Stream<Item = Result<Event, Infallible>>> {
  let stream = stream::repeat_with(|| {
    Event::default().data("update")
  })
  .map(Ok)
  .throttle(Duration::from_secs(1));
  Sse::new(stream).keep_alive(KeepAlive::default())
}
Enter fullscreen mode Exit fullscreen mode

One function. Returns a stream. The runtime handles backpressure, keep-alive, and client disconnection. No connection tracking. No upgrade handshake. Plain HTTP.

The Protocol

Three headers. That is the entire specification:

Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
Enter fullscreen mode Exit fullscreen mode

The server sends lines prefixed with data:. The browser parses them. No frame encoding. No masking. No opcodes. HTTP from start to finish. Every proxy understands it. Every CDN can pass it through.

When To Use

One-way server push: SSE. Dashboards, notifications, logs, feeds, progress bars.

Bidirectional: WebSocket. Chat, multiplayer, collaborative editing.

If the client never sends, SSE is simpler, lighter, and recovers from failure without your help. One rather appreciates infrastructure that does not require a babysitter.

Read the full article on vivianvoss.net →


By Vivian Voss — System Architect & Software Developer. Follow me on LinkedIn for daily technical writing.

Top comments (0)