{"post":{"slug":"what-is-server-sent-events-2026","title":"What Are Server-Sent Events in 2026? SSE Explained","excerpt":"Server-sent events let a server push updates to the browser over plain HTTP, with reconnection built in. Here is how the wire format and EventSource API actually work in 2026.","category":"code","date":"July 23, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">S</span>erver-sent events, usually shortened to SSE, let a server push updates to a browser without the browser having to ask again and again. There is no special protocol involved — SSE is a plain HTTP response that the server simply never closes, writing small text messages to it as new data arrives. The browser reads that stream through the `EventSource` API, which parses each message and, if the connection ever drops, reconnects automatically. That combination of simplicity and built-in reliability is why SSE quietly became the default transport for AI streaming responses, live tickers, and notification feeds.\n\n## What changed in 2026\n\n- **AI streaming responses made SSE mainstream knowledge.** Every major LLM API streams its output as SSE under the hood, so developers who never touched real-time features directly are now debugging event streams regularly.\n- **HTTP/2 and HTTP/3 removed the old connection cap.** Browsers used to limit six connections per domain over HTTP/1.1, which forced awkward workarounds for pages with multiple SSE streams. That limit does not apply once the connection is multiplexed.\n- **Framework-level streaming responses got simpler.** Next.js route handlers, Remix, and SvelteKit now support returning a streaming `Response` directly, cutting the boilerplate an SSE endpoint used to need.\n- **fetch-based SSE clients became a common alternative to EventSource.** The native `EventSource` object cannot set custom request headers, so teams needing bearer-token auth increasingly parse the stream manually from a `fetch` call instead.\n\n## How the wire format works\n\nAn SSE message is plain text, sent as a series of `field: value` lines, ended by a blank line:\n\n```\nevent: price_update\ndata: {\"symbol\":\"ACME\",\"price\":42.17}\nid: 91\nretry: 3000\n\ndata: heartbeat\n\n```\n\n`data` carries the payload, `event` names the event type (it defaults to a generic \"message\" if omitted), `id` is remembered by the browser as the Last-Event-ID for reconnection, and `retry` sets how long the browser waits before reconnecting after a drop.\n\n## A minimal client and server\n\n```javascript\n// server.js (Express)\napp.get(\"/api/stream/prices\", (req, res) => {\n  res.set({\n    \"Content-Type\": \"text/event-stream\",\n    \"Cache-Control\": \"no-cache\",\n    Connection: \"keep-alive\",\n  });\n  res.flushHeaders();\n\n  const id = setInterval(() => {\n    const price = getLatestPrice(\"ACME\");\n    res.write(`event: price_update\\ndata: ${JSON.stringify(price)}\\n\\n`);\n  }, 2000);\n\n  req.on(\"close\", () => clearInterval(id));\n});\n```\n\n```javascript\n// client\nconst stream = new EventSource(\"/api/stream/prices\");\n\nstream.addEventListener(\"price_update\", (e) => {\n  updateTicker(JSON.parse(e.data));\n});\n\nstream.onerror = () => console.log(\"Reconnecting automatically...\");\n```\n\nNo library is required on either side. The browser handles parsing, reconnection, and event dispatch on its own.\n\n## SSE versus the alternatives\n\n| Approach | Server push | Reconnect handling | Complexity |\n| --- | --- | --- | --- |\n| Polling (setInterval + fetch) | No, client asks repeatedly | Not applicable | Low, but wasteful |\n| Long polling | Simulated | Manual | Medium |\n| SSE (EventSource) | Yes, native | Automatic, with Last-Event-ID | Low |\n| WebSockets | Yes, bidirectional | Manual | Medium to high |\n\n## When SSE fits and when it does not\n\nSSE is a solid default for live notifications, activity feeds, AI-generated streaming text, score or price tickers, build and deploy logs, and any one-way dashboard. It is the wrong choice when the client also needs to send frequent messages back over the same channel — that is what WebSockets are built for. For the full bidirectional-versus-one-way decision, including how authentication and debugging differ between the two, see [WebSockets vs server-sent events](/blog/websockets-vs-server-sent-events-2026).\n\n## Common mistakes and limitations\n\n**Forgetting Cache-Control: no-cache.** Without it, some proxies buffer the response and delay every message, which defeats the point of a live stream.\n\n**Trying to send binary data.** SSE is a text protocol end to end. Binary payloads have to be base64-encoded first, which adds overhead — for real binary streaming, look elsewhere.\n\n**Assuming EventSource can set custom headers.** It cannot. Most implementations authenticate through cookies sent automatically with the request, or a token in the URL query string, since a bearer-token header is not an option with the native API.\n\n**Skipping the id field when you actually need resumability.** Without an id on each message, a reconnect after a drop starts fresh instead of picking up where the client left off.\n\n## FAQ\n\n**Can SSE send binary data?**\nNot directly. SSE is a text protocol, so every message is UTF-8 text. Binary payloads must be base64-encoded first, which adds overhead, making SSE a poor fit for large binary transfers.\n\n**Can the client send data back over an SSE connection?**\nNo. SSE is one-way, server to client only. The client sends any input through a normal separate HTTP request, not through the EventSource connection itself.\n\n**How does authentication work with SSE?**\nThe native EventSource API cannot set custom request headers, so most implementations authenticate through cookies or a token in the URL. A fetch-based streaming client is the usual workaround when a bearer token in a header is required.\n\n**What happens if the SSE connection drops?**\nThe browser reconnects automatically, roughly three seconds later by default unless the server sent a different retry value. If the server included id fields, the browser resends the last one as a Last-Event-ID header so the server can resume from that point.\n\n## Where to go next\n\n- [WebSockets vs server-sent events in 2026](/blog/websockets-vs-server-sent-events-2026)\n- [What is a web worker in 2026](/blog/what-is-a-web-worker-2026)\n- [What is a progressive web app in 2026](/blog/what-is-a-progressive-web-app-2026)","hue":200,"metaTitle":"Server-Sent Events Explained 2026: SSE and EventSource","metaDescription":"Server-sent events explained for 2026: the EventSource API, the event-stream format, automatic reconnection, and when SSE beats polling or websockets.","keywords":["server sent events 2026","what is sse","eventsource api","server sent events vs polling","sse wire format","text event-stream","sse reconnection last event id","server sent events example","one way streaming http"],"tldr":["**SSE is a long-lived HTTP response, not a special protocol** — the server keeps writing text to an open connection and the browser reads it as it arrives.","**The wire format is plain text lines** — data, event, id, and retry fields separated by newlines, with a blank line ending each message.","**EventSource handles reconnection for you** — if the connection drops, the browser retries automatically and sends the last event id so the server can resume.","**SSE only flows one way, server to client** — the client cannot send messages back over the same connection, only through a separate request.","**Skip:** building your own polling loop for live updates — SSE does the same job with less code and far less server load once you have tried it."],"readTime":"4 min read","wordCount":879},"related":[{"slug":"server-sent-events-explained-2026","title":"Server-Sent Events in 2026: A Simpler Real-Time Option","excerpt":"Server-Sent Events push updates to the browser over one plain HTTP response, with automatic reconnection built in. This guide explains how SSE works and when it beats WebSockets for simplicity.","category":"code","date":"August 9, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":308},{"slug":"websockets-vs-server-sent-events-2026","title":"WebSockets vs Server-Sent Events in 2026: Auth and Debugging","excerpt":"WebSockets and server-sent events both power real-time features, but they differ sharply on authentication, reconnection, and how you debug them. Here is a scenario-based way to choose in 2026.","category":"code","date":"July 16, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":240},{"slug":"what-is-a-webhook-2026","title":"What is a webhook in 2026? Event-driven notifications explained","excerpt":"A webhook is an automated message a service sends to your app the moment something happens. This guide explains how webhooks work, how they differ from APIs, and how to use them safely in 2026.","category":"code","date":"May 7, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":240}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"what-is-sequence-risk-in-retirement-2026","title":"What Is Sequence Risk in Retirement? The 2026 Explainer","excerpt":"Sequence-of-returns risk means the order of your investment returns in early retirement can matter more than their average. A 2026 guide to spotting it.","category":"finance","date":"July 23, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":265},"older":{"slug":"what-is-server-side-rendering-hydration-2026","title":"What is server-side rendering and hydration in 2026?","excerpt":"Server-side rendering sends finished HTML on the first response, and hydration is the step that makes it interactive. Here is how the two work together in 2026, and where teams get the handoff wrong.","category":"code","date":"July 23, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":150}}