The SSE Connection Lifecycle
Server-Sent Events (SSE) establish a persistent HTTP connection where the server pushes data to the client using the `text/event-stream` MIME type. Unlike WebSockets, SSE is unidirectional (server-to-client) and leverages standard HTTP semantics. The `EventSource` interface manages this connection, automatically attempting to reconnect if the connection drops.
When an `EventSource` object is created, its `readyState` is initialized to `CONNECTING` (0). Once the connection is established and the server responds with the correct content type, the state transitions to `OPEN` (1), and the client begins parsing the stream. If a network error occurs or the connection drops, the browser automatically queues a task to reestablish the connection after a delay (the reconnection time), transitioning back to `CONNECTING` and firing an `error` event.
Automatic Reconnection Behavior
The automatic reconnection feature of SSE is highly resilient. If the connection fails, the user agent waits for a specified delay before retrying. This delay can be controlled by the server using the `retry` field in the event stream. If the previous attempt failed, browsers may introduce exponential backoff to avoid overloading the server.
Crucially, the client will stop attempting to reconnect only under specific conditions: if the server responds with an HTTP 204 No Content, if the response status is not 200, or if the `Content-Type` is not `text/event-stream`. If the connection is explicitly closed by the client using the `close()` method, the `readyState` becomes `CLOSED` (2), and no further reconnection attempts are made.
State Recovery with Last-Event-ID
To ensure no events are lost during a disconnect, SSE utilizes the `id` field. When the server includes an `id` field in an event block, the client updates its internal last event ID string. If the connection drops and the client attempts to reconnect, it includes this value in the `Last-Event-ID` HTTP request header.
The `Last-Event-ID` header allows the server to determine exactly where the client left off and resume the stream from that point. The server must track event IDs and retain a buffer of recent events to serve reconnecting clients. If an event contains an empty `id` field, the client resets its last event ID string, meaning no `Last-Event-ID` header will be sent on subsequent reconnects.
Implementation Tradeoffs and Failure Modes
Implementing robust SSE requires managing state on the server. Buffering events for reconnecting clients consumes memory. If the server restarts or the buffer is cleared, a client connecting with a valid `Last-Event-ID` might request an event that no longer exists. The server must handle this gracefully, perhaps by sending a full state snapshot instead of a delta.
Another common failure mode involves proxy servers. Legacy proxies may drop long-lived HTTP connections after a timeout. To prevent this, servers can send periodic "keep-alive" comments (lines starting with a colon). Additionally, HTTP chunking implemented by intermediary layers unaware of SSE timing requirements can delay event delivery. Disabling chunking for event streams may be necessary in some environments.
Test Matrix and Worked Example
When testing SSE endpoints, it is critical to verify reconnection logic and authorization enforcement. Consider a hypothetical synthetic fixture where an SSE endpoint `/api/stream` requires a valid session cookie. A safe test matrix should verify the following expected outcomes:
1. **Initial Connection**: Valid cookie -> HTTP 200, `text/event-stream`. 2. **Reconnect with Last-Event-ID**: Valid cookie, `Last-Event-ID: 42` -> HTTP 200, stream resumes from event 43. 3. **Expired Session Reconnect**: Invalid cookie -> HTTP 401, browser stops reconnecting. 4. **Missing Event ID**: Valid cookie, `Last-Event-ID: 9999` (event purged) -> HTTP 200, server sends full state snapshot or error event indicating state loss. 5. **Incorrect Content-Type**: Valid cookie -> HTTP 200, `application/json` -> browser fails connection.
- Valid session: HTTP 200, correct MIME type.
- Invalid session on reconnect: HTTP 401/403, halting reconnects.
- Purged Last-Event-ID: Graceful state recovery.
Sources
HTML Standard: Server-sent events - https://html.spec.whatwg.org/multipage/server-sent-events.html
Drafted with Gemini and checked for source links, advisory identifiers, structure and unsupported product claims. Examples are synthetic and are not scan results.
Drafted with Gemini and checked for source links, advisory identifiers, structure and unsupported product claims. Examples are synthetic and are not scan results.
Prepared with AI assistance and published by WarHound AI. Check the references and evidence limits in each article.
The WarHoundAI journalQuestions or a factual correction? Get in touch with the article URL and supporting evidence.