SSE in Go: Your Timeouts Do Not Apply Where You Think
An SSE stream is an HTTP request that never ends. Every default you did not touch is working against it. TL;DR : your SSE endpoint breaks twice before it reaches your logic. Once because the Connection header is illegal in HTTP/2. Once because your Go server's default timeouts cut the stream at 30 seconds. And if you stay on HTTP/1.1, a permanent stream freezes the rest of your page. In August 2026, Go patched a flaw where a timeout was not applied to HTTP/2 connections. Same lesson: a timeout only protects what it covers. This article is for Go developers shipping streaming to production. SSE, WebSocket, long-poll: anything that stays open. The setup SSE stands for Server-Sent Events. It is a one-way HTTP stream. The server pushes messages, the browser listens. The format is simple. You open a text/event-stream response, you write lines, you flush. The browser receives them as they come. I run two SSE endpoints in production. The first is a Go notification service, on Kubernetes, behind a reverse proxy. The second is an internal cockpit that refreshes its UI without a page reload. Both broke. In different places, with the same symptom. An SSE stream is a request that never ends Here is the key to the whole article. To your server, an SSE stream is not a special case. It is a very slow request. And every guardrail in an HTTP server targets the slow request. Write timeout, context timeout, idle timeout. They exist to kill whatever drags on. Your legitimate stream looks exactly like what they are meant to kill. That is the whole problem. The Connection header is illegal in HTTP/2 First incident. The endpoint answers 200, then the browser shows net::ERR_HTTP2_PROTOCOL_ERROR . The client reconnects in a loop. The cause was one line. My handler set a Connection: keep-alive header. We all copy it from some old SSE tutorial. Connection is a hop-by-hop header. A hop-by-hop header applies to one network hop only, never end to end. HTTP/2 forbids these headers (RFC 9113 §8.2.