A live page may need the server to push updates, the client to send frequent messages, or both. Server-sent events provide a one-way stream from server to browser over HTTP and fit a status feed that the user only reads. WebSocket provides a two-way connection when both sides exchange low-latency messages. Neither removes the need for authentication, per-record authorization, reconnect policy, and stale event handling. Start with polling when update frequency is low; a persistent connection has server and proxy costs. Define event IDs and payload shape before selecting a transport.
Server-Sent Events or WebSocket for Live Views
Working case
A case queue needs to show that inspection 93 changed to approved within seconds. The browser does not send live edits; a one-way event stream is enough. The page opens an EventSource for case 47 and updates a status node when a validated event arrives. If the connection closes, the browser can reconnect, but the server must support a safe resume or full refresh. A collaborative annotation board with continuous edits in both directions would justify a different transport. A live UI should still show an initial state from a normal page or read request.
Implementation
const statusNode = document.querySelector("#case-status");
const updates = new EventSource("/cases/47/events");
updates.addEventListener("status", (event) => {
const payload = JSON.parse(event.data);
if (payload.caseId !== 47 || typeof payload.status !== "string") return;
statusNode.textContent = payload.status;
});
addEventListener("pagehide", () => updates.close());Cost and boundaries
A persistent stream keeps a connection and server resources open for each active reader. Fan-out work can approach O(C) per event for C connected clients unless an intermediary distributes it. Polling costs repeated requests even when nothing changes; choose based on measured frequency and infrastructure constraints. A slow consumer needs buffering limits so memory cannot grow without bound. On page exit, close the stream to release resources. The snippet updates text, not HTML, and leaves the initial case view intact.
Common Mistakes
- Do not select WebSocket for a read-only status page without a need for two-way messages.
- Do not assume reconnecting guarantees no lost events.
- Do not insert event payloads as untrusted HTML.
Connected lessons
Media and Live Updates; Safe File Upload Pipeline; Image Variants and Delivery Budgets; Live Update Reconnect and Event Ordering; Page loading: keep content available while CSS and scripts arrive; Fetch requests: separate HTTP failure, transport failure, and cancellation; HTML srcset and sizes: let the browser choose an appropriately sized image.
Failure trace
A team opens a WebSocket for a status label that changes once an hour. The connection infrastructure becomes the busiest part of the system, while a missed event still leaves the label stale. Start from the update contract: periodic polling may be enough; one-way events fit a frequent feed; two-way transport is justified when the browser must send live messages. In each case, a normal read supplies the starting state.
Verification
- Disconnect the live channel and confirm the page still shows its last known state with a stale indicator.
- Reconnect after one missed update and compare with a fresh server snapshot.
- Measure open connections and per-event fan-out at the expected concurrent-reader count.
Decision note
Transport choice cannot replace event identity, authorization, or replay policy. State the freshness target first, then measure whether the simpler delivery method meets it.
Apply and check
Build Project: live review board with ordered status; then check the boundary with Web Development: offline and delivery contracts quiz.
Further connections
WebRTC ICE, TURN Fallback, and Session Recovery.
Further connections
Realtime Connection and Event Delivery; WebSocket Handshake, Session, and Channel Authorization.
