WebSocket & Real-time
WebSocket, Socket.IO, SSE, long polling -- protocols and when to use each.
websocketrealtimebackendfrontend
# WebSocket & Real-time
## Protocol comparison
| | WebSocket | SSE | Long Polling |
|---|---|---|---|
| Direction | Bidirectional | Server->Client | Server->Client |
| Overhead | Low | Medium | High |
| Reconnect | Manual | Auto | Auto |
| Binary | Yes | No | No |
## WebSocket (native)
```ts
// Server (ws library)
const wss = new WebSocketServer({ port: 8080 })
wss.on('connection', (ws) => {
ws.on('message', (msg) => ws.send('echo: ' + msg))
ws.on('close', () => console.log('disconnected'))
})
// Client
const ws = new WebSocket('wss://example.com/ws')
ws.onopen = () => ws.send(JSON.stringify({ type: 'ping' }))
ws.onmessage = (e) => console.log(JSON.parse(e.data))
ws.onclose = () => setTimeout(reconnect, 2000)
```
## Socket.IO
Abstracts WS + fallback. Adds rooms, namespaces, auto-reconnect, ack.
```ts
// Server
io.on('connection', socket => {
socket.join('room1')
socket.on('msg', data => io.to('room1').emit('msg', data))
})
// Client
socket.emit('msg', { text: 'hi' })
socket.on('msg', handler)
```
## SSE (Server-Sent Events)
```ts
res.setHeader('Content-Type', 'text/event-stream')
res.setHeader('Cache-Control', 'no-cache')
const id = setInterval(() => {
res.write('data: ' + JSON.stringify({ t: Date.now() }) + '\n\n')
}, 1000)
req.on('close', () => clearInterval(id))
// Client
const es = new EventSource('/stream')
es.onmessage = e => console.log(JSON.parse(e.data))
```
## Scaling WebSockets
- Connections are stateful -> sticky sessions at LB.
- Redis pub/sub to fan out events across server instances.API: /api/skills/websocket-realtime