Skip to content

SSE: emit periodic keepalive heartbeats so idle streams survive proxy timeouts #226

Description

@EricAndrechek

Area: streaming (api) · ops — reliability gap · found via WaveHouse-Stats dogfooding (reproduced live)

Expected: a long-lived SSE stream survives through a CDN/proxy even with no events flowing.

Actual: the handler writes : connected once (internal/api/stream.go:67) then sends nothing until an event arrives — the select loop (:116-145) has only context-done and incoming-event cases, no heartbeat ticker. On a quiet stream an intermediary (Cloudflare's edge idle-timeout, ~2 min) resets the idle HTTP/2 stream with INTERNAL_ERROR. Browser EventSource auto-reconnects so it's masked there, but curl/server-side consumers drop repeatedly and each reconnect re-runs gap-fill.

Impact (Stats): curl against /v1/stream?table=gh_events dies ~every 2 min while the table is quiet; we wrap it in a reconnect loop.

Scope: periodic SSE comment heartbeat on a ticker, added to the select loop.

Related: SSE per-subscriber channel buffer sizing #152 (same handler).


From WAVEHOUSE-FEEDBACK.md (WaveHouse-Stats dogfooding); validated by code-read against 0f8826c on 2026-06-04.

Metadata

Metadata

Assignees

Labels

area/apiHTTP handlers, routing, middlewarearea/observabilityMetrics, logs, traces, health, profilingbugSomething isn't working

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions