SSE

Background

  • enables efficient server-to-client streaming of text-based event data
    • eg. real-time notifications or updates generated by the server
  • two new components: EventSource interface & “event stream” data format
    • EventSource interface allows the client to receive push notifications from the server as DOM events
    • “event stream” data format is used to deliver the individual updates
  • efficient way to handle real-time data in the browser
    • low latency via a single, long-lived connection
    • efficient browser message parsing with no unbounded buffer
    • automatic tracking of last seen message and auto connect
    • client messages as DOM events
  • is essentially a efficient, cross-browser implementation of XHR streaming
    • except the browser handles all the connection management and message parsing

EventSource API

  • need to specify the URL of the SSE event stream, resource and resister the appropriate JS event listeners on the object
  • implementation logic is handled by the browser
    • connection is negotiated on our behalf, received data is parsed incrementally, message boundaries are identified, and finally a DOM event is fired by the browser
  • SSE provides a memory-efficient implementation of XHR streaming
    • raw XHR connection buffers the full received response until the connection is dropped
    • SSE connection can discard processed messages
  • if the connection is dropped, EventSource will automatically reconnect and optionally advertise the ID of the last seen message, such lost messages can be retransmitted
  • on browsers that do not support EventSource API natively, we can emulate it with an optional JS library (ie. a “polyfill”) - but it will not be as efficient
    • XHR polling incurs message delays and high request overhead
    • XHR long-polling minimizes latency delays but has high request overhead
    • XHR streaming support is limited and buffers all the data in memory

Event Stream Protocol

  • an SSE event stream is delivered as a streaming HTTP response: the client initiates a regular HTTP request, the server responds with a custom “text/event-stream” content-type, then streams the UTF-8 encoded event data
  • event-stream protocol is quite trivial to understand and implement
    • event payload is the value of one or more adjacent data fields
    • event may carry an optional ID and an event type string
    • event boundaries are marked by newlines
  • on the client side: parse by looking for newline separators extract payload check for ID & type dispatch DOM event to notify the application
    • if a type is present, then a custom DOM event is fired, and otherwise the generic “onmessage” callback is invoked

SSE Use Cases & Performance

  • low latency - messages can be pushed the moment they become available on the server

  • min message overhead - long lived-connection, event-stream protocol, gzip compression

  • auto-reconnect, message notifications as DOM events

  • SSE has two main limitations

    • does not address the request streaming use cases (eg. streaming a large upload to the server)
    • specifically designed to transfer UTF-8 data, binary streaming, while possible, is inefficient (base64 encoding an arbitrary binary object incurs a 33% byte overhead)
      • can be resolved at the application layer - SSE delivers a notification about an available binary asset, and the application dispatches an XHR request to fetch it
        • +1 RTT, but leverages the services provided by XHR - response caching, transfer-encoding (compression), etc
        • streamed assets cannot be cached by the browser cache
  • note that real-time push, just as polling, can negatively impact battery - consider batching messages, and eliminate unnecessary keepalives; an SSE connection is not dropped while the radio is idle

  • SSE is a simple and convenient on top of a regular HTTP connection, but existing network middleware (eg. proxy servers, firewalls), which are not SSE aware may cause problems - intermediaries may choose the buffer the event-stream data, which translates to increased latency or a broken SSE connection

    • can consider delivering an SSE event-stream over a TLS connection (instead of HTTP)
      • according to Chat: when traffic is encrypted with TLS, the intermediaries are unable to inspect the contents of the messages and thus more likely to fwd it as-is instead of manipulating it

browser networking