The live scorecard

A sports site wants live score updates during a match. Thousands of users watching, a few updates per minute, read-only from the client. Websockets would work. Server-Sent Events are simpler and built for exactly this shape.

SSE is a one-way HTTP stream from server to client. The server keeps the response open and writes a line every time there is an update. The browser has a built-in EventSource API that handles reconnection automatically. Simpler than websockets when the client never needs to send anything back.

server.ts
typescript
app.get('/scores/:matchId/stream', (req, res) => {
  const { matchId } = req.params;

  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
  res.flushHeaders();

  const listener = (update: ScoreUpdate) => {
    res.write('data: ' + JSON.stringify(update) + '\n\n');
  };

  matchEvents.on(matchId, listener);

  req.on('close', () => {
    matchEvents.off(matchId, listener);
  });
});

The entire SSE endpoint is just keeping a response open and writing event lines.

client.ts
typescript
const source = new EventSource('/scores/123/stream');
source.onmessage = (e) => {
  const update = JSON.parse(e.data);
  renderScore(update);
};

The browser API handles reconnection automatically.

Quiz: Quiz

Loading practice…