Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use a Next.js App Router GET Route Handler to return a Web ReadableStream, then format every message according to the Server-Sent Events protocol. A stream that works in the handler can still appear all at once if a proxy buffers it, and EventSource reconnecting does not recover messages your application never saved. This guide covers the endpoint, the wire format, reconnect and replay decisions, and checks to run through your actual deployment path.
How do I use Server-Sent Events (SSE) with the Next.js App Router?
Create a Route Handler at an app/**/route.ts path and return a Web Response whose body is a ReadableStream. The handler is the endpoint primitive; it does not format SSE records for you. Next.js documents the Route Handler conventions and generic stream mechanics in its Route Handler reference.
As an Amazon Associate I earn from qualifying purchases.
This minimal example emits a JSON message every five seconds. It is a live-only example: it does not store messages or promise that a reconnecting client will catch up. Replace the interval producer with your application’s event source, such as a subscription to a job or notification service.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteconst encoder = new TextEncoder();
export async function GET(request: Request) {
let timer: ReturnType<typeof setInterval> | undefined;
let closed = false;
let controllerRef: ReadableStreamDefaultController<Uint8Array> | undefined;
const cleanup = () => {
if (closed) return;
closed = true;
if (timer !== undefined) clearInterval(timer);
request.signal.removeEventListener("abort", cleanup);
};
const stream = new ReadableStream<Uint8Array>({
start(controller) {
controllerRef = controller;
const send = (value: unknown) => {
if (closed) return;
try {
// JSON.stringify produces a single-line data value for ordinary JSON payloads.
controller.enqueue(encoder.encode(`data: ${JSON.stringify(value)}nn`));
} catch {
cleanup();
try {
controller.close();
} catch {
// The consumer may already have cancelled the stream.
}
}
};
send({ type: "connected", at: new Date().toISOString() });
timer = setInterval(() => {
send({ type: "update", at: new Date().toISOString() });
}, 5000);
if (request.signal.aborted) cleanup();
else request.signal.addEventListener("abort", cleanup, { once: true });
},
cancel() {
cleanup();
controllerRef = undefined;
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream; charset=utf-8",
"Cache-Control": "no-cache, no-transform",
},
});
}
The example demonstrates stream construction, encoding, and timer cleanup; it is not a production event broker. In a real handler, ensure the cancellation path unsubscribes from upstream work as well as clearing timers. The Web Streams cancellation lifecycle is the place to stop the producer when the consumer cancels; whether a disconnect is promptly propagated through the whole hosting stack must be checked in that deployment.
#1 Best Overall
Cache-Control above is a practical choice for a live feed, not an SSE-mandated header. Select cache behavior for your use case. The essential protocol response type is text/event-stream.
What must an SSE event contain?
An EventSource response is UTF-8 text with fields written as lines. A blank line ends a record. For the protocol details, see the MDN SSE guide and the WHATWG HTML Standard, Server-sent events.
data:carries the event payload. Multipledata:lines are joined with newline characters by the browser.event:optionally gives the event a name, which the client can listen for specifically.id:optionally sets the event ID used by EventSource when reconnecting.retry:optionally supplies a reconnection delay in milliseconds.- A line beginning with
:is a comment, not an application event. It can be used as a keepalive.
For a JSON object, serializing with JSON.stringify gives a convenient single-line data: value. If sending arbitrary multiline text rather than JSON, emit each line as its own data: field and then terminate the record with a blank line. Do not treat a comment or heartbeat as a data event.
Rank #2
event: order-update
id: 8421
data: {"orderId":"A17","status":"shipped"}
: keepalive
In a browser, the default message listener receives records without an event: name. Named records use addEventListener:
const source = new EventSource("/api/events");
source.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data);
};
source.addEventListener("order-update", (event) => {
const data = JSON.parse((event as MessageEvent).data);
console.log(data);
});
source.onerror = () => {
// EventSource normally attempts to reconnect unless closed by the application.
};
How do I reconnect to a Next.js SSE stream?
The browser’s EventSource reconnects after a dropped connection by default. A server can send a retry: field to set the reconnection delay. If the stream has sent an id:, the browser retains that ID and sends it on a later connection in the Last-Event-ID request header, as specified by the WHATWG standard.
Those mechanics restore a connection; they do not create a message history. Decide explicitly whether reconnecting clients need to resume from a cursor:
Rank #3
- Live-only feed: omit IDs if they have no useful meaning, or document that a reconnect receives only future events. Messages sent while disconnected may be missed.
- Catch-up feed: assign each event a stable ID from a durable ordered log or equivalent cursor source. Read and validate
Last-Event-ID, then replay events after that cursor before switching to live delivery.
Do not use an in-memory counter or a process-local value as a durable cursor when requests can land on different instances or a process can restart. Define what happens if the cursor is malformed, expired, or no longer present in the event store; for example, reject it or direct the client to refresh its state. Exactly-once delivery does not follow from EventSource reconnecting: applications that require reliable processing need their own cursor, replay, and duplicate-handling policy.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWhy does my SSE endpoint send events all at once?
A handler may enqueue events incrementally while an intermediary holds the response until it has buffered enough data or the response ends. Next.js warns that reverse proxies and load balancers must pass streaming responses without buffering; its self-hosting guide says nginx or a similar proxy may need buffering disabled, suggests X-Accel-Buffering: no for nginx, and notes that some cloud load balancers buffer by default.
Configure the infrastructure actually in front of the application: CDN, gateway, reverse proxy, load balancer, and hosting runtime. For nginx, the response header can be added where appropriate:
"X-Accel-Buffering": "no"
That header is an nginx-related hint, not a universal switch for every intermediary. Confirm each layer’s buffering and idle-timeout behavior in its own configuration. Vercel documents streaming support for Next.js, but it is one hosting option rather than a requirement; self-hosting can stream when the proxy and load-balancer path is configured to do so.
Keepalive comments may help prevent an otherwise idle connection from being closed, but choose the heartbeat interval against the real idle timeouts on the route. The protocol sources do not establish one universally safe interval.
How should I test the full production path?
Test the deployed URL rather than relying only on a local Route Handler test. The point is to distinguish application framing from buffering or disconnect behavior in the network path.
- Open the endpoint with a streaming-capable client, for example
curl -N https://your-host.example/api/events. Verify the response hasContent-Type: text/event-streamand that complete records arrive at intervals instead of appearing only when the connection ends. - Leave the connection idle long enough to exercise your heartbeat and the relevant proxy or load-balancer idle timeout. Confirm comments do not appear as application messages in the browser.
- Drop the connection and let the browser’s EventSource reconnect. If the product promises catch-up, verify that the new request’s
Last-Event-IDis validated and that missing records are replayed from the chosen durable source. - Close the browser tab or cancel the client connection. Confirm the Route Handler’s cancellation path stops timers and upstream subscriptions rather than leaving producer work running.
Run these checks after deployment or proxy changes as well as during development: an endpoint can be correctly framed and still fail to deliver incrementally through a changed infrastructure path.
How many SSE connections can a browser keep open?
MDN Web Docs, accessed October 4, 2026, reports a limit of six open SSE connections per browser and domain outside HTTP/2. With HTTP/2, the number of simultaneous streams is negotiated, with a default of 100 cited by MDN. These are browser and transport-qualified figures, not universal server capacity limits; actual negotiated settings and deployment resources matter. The figures are documented in the MDN SSE guide.
If a page opens multiple feeds, account for connections shared across tabs and consider consolidating events behind a single stream per relevant origin. Separately assess server-side connection capacity, subscription fan-out, and the chosen HTTP transport.
Free tools Windows power users keep installed
One-click scans. No signup required.
Is Next.js page streaming the same as SSE?
No. Next.js and React can stream server-rendered page output, for example through route loading UI and Suspense, while an SSE endpoint is a long-lived response with the EventSource MIME type and event-record framing. The capabilities may both use streaming underneath, but streaming rendered HTML does not turn a page response into an SSE feed. Vercel documents Next.js streaming across Route Handlers, Functions, and React Server Components in its Next.js documentation; use a Route Handler and the SSE wire format when the browser should consume server-to-browser events.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




