Heartbeats and reconnect — part of the protocol, not an add-on
Heartbeats and reconnect belong in the transport protocol from day one — not as a later patch.
nestjs-realtime-stream-heartbeats-reconnect
Why it matters
| Stake | If ignored |
|---|---|
| Drops connection |
|
| Bad UX |
|
How to fix
- SSE: emit an empty comment (
:heartbeat\n\n) every 15–30 seconds; on reconnect the client sendsLast-Event-Idto resume. - WebSocket: rely on ping/pong (socket.io does this automatically) and exponential backoff on reconnect.
- For durable runs, pair heartbeats with explicit cancel/resume policy (see related streaming rules).
Examples
ts
@Sse('runs/:id/events')
streamRun(@Param('id') runId: string): Observable<MessageEvent> {
return this.runs.events(runId);
}ts
@Sse('runs/:id/events')
streamRun(@Param('id') runId: string): Observable<MessageEvent> {
return merge(
this.runs.events(runId),
interval(15_000).pipe(map(() => ({ type: 'heartbeat', data: '' } as MessageEvent))),
);
}
// frontend
const sse = new EventSource(`/runs/${runId}/events`);
// EventSource auto-reconnects with Last-Event-Id when the server emits `id:` on every event