Messaging
Part 4 of 6 · WebSockets & MQTTWebSocket vs SSE vs Long-Polling vs MQTT — When to Choose What
Choose a realtime channel from directionality, client environment, proxies, battery, topic routing, and durability. Pick the simplest protocol that fits; bridge to Kafka only when replay is a product requirement.
- 1Gist
- 2Maps
- 3Q&A
- 4Sandbox
Voice readout needs Web Speech Synthesis in this browser.
Simplest protocol that meets direction + environment
Prefer
Start SSE or REST; upgrade the channel when the product needs it
Notification bells are SSE. Typing indicators need WebSocket. Sensors need MQTT. Replay needs a log. Each step is additive — you do not rewrite the browser path when devices arrive.
- HTTP/2 multiplexing makes SSE practical (HTTP/1.1 ~6 connections per host).
- MQTT-over-WS gives browsers topics/QoS without raw TCP.
- Long-poll only when Upgrade is stripped.
Alternative
WebSocket for everything, or MQTT QoS 2 instead of Kafka
A chat library default is not a protocol choice. Tunneling REST over WebSocket wastes a long-lived socket. Shared MQTT subscriptions are not Kafka partition assignment.
- SSE cannot carry binary file transfer — use HTTP download.
- Zero-jitter long-poll becomes a reconnect storm.
- Dual-writing WS and MQTT without an event id duplicates the UI.
Interview decision order
Ask direction first. Durability last. Kafka is a bridge, not a substitute for the push channel.
- 1
Need live updates?
If not, HTTP request/response. Do not open a socket to tunnel REST. - 2
Bidirectional?
No → SSE (or MQTT if the client is a device). Yes → WebSocket in a browser, MQTT on MCU/native. - 3
Hostile proxy?
Strips streaming / Upgrade → long-poll fallback with jitter. - 4
Need durable replay?
Bridge high-value events to Kafka. Do not stretch MQTT QoS 2 into a log.
Overview
Build a decision matrix for real-time delivery so interviews get a crisp why this, not that.
Decision drivers
- Direction — uni (server→client) vs bi
- Client — browser, native mobile, MCU/IoT
- Network — corporate proxies, HTTP/2, TLS middleboxes
- Scale shape — many rooms, many devices, broadcast vs address
- Durability — ephemeral push vs replayable log (Kafka elsewhere)
- Auth — cookie/header on WS upgrade vs MQTT CONNECT / mTLS
Matrix
| Option | Direction | Client | Watch |
|---|---|---|---|
| WebSocket | Bidirectional | Browser-native | Sticky or fan-out bus; proxy idle; backpressure |
| SSE | Server→client | Browser EventSource | Auto-retry + Last-Event-ID; HTTP/1.1 connection caps; no binary frames |
| Long-polling | Emulated push | Almost everywhere | Highest overhead; latency ≥ poll interval; reconnect herds |
| MQTT | Bidirectional pub/sub | Devices, mobile, brokers | QoS, LWT, sessions; another moving part; ACL mistakes |
| Kafka | Not a push API | Consumers | Durable processing/replay; bridge from the above |
Pros / cons / failure modes
WebSocket: full duplex. Watch proxy idle timeouts, sticky affinity, backpressure. Depth: handshake and scaling.
SSE: simple ops. Watch ~6 connections per host on HTTP/1.1; prefer HTTP/2. No binary frames. Pair with POST for client→server.
Long-polling: works almost everywhere. Thundering herd on timeout alignment. Jitter; cache ETag / Last-Modified.
MQTT: rich messaging semantics. Broker ops and ACL. Depth: essentials and brokers.
When MQTT-over-WebSocket
Browsers lack raw MQTT TCP. Use WS transport to the broker. You still get topics and QoS; you still inherit WebSocket scaling concerns at the edge (sticky, idle timeout, fan-out). That is a transport, not a free lunch.
Auth differs: WS often cookie/header on upgrade; MQTT CONNECT username/password or mTLS at the broker.
Direction first. One-way stays on SSE; duplex picks WebSocket or MQTT next.
Decisions
- 1
1 Need live updates?
- next2 Bidirectional?
- ?
2 Bidirectional?
- no4 Prefer SSE
- yes3 Browser UI?
- 3
4 Prefer SSE
- 4
3 Browser UI?
Lesson map
WebSocket vs SSE vs Long-Polling vs MQTT — When to Choose What
Choose a realtime channel from directionality, client environment, proxies, battery, topic routing, and durability. Pick the simplest protocol that fits; bridge to Kafka only when replay is a product requirement.
Architecture. Architecture
Select a node to see why it exists, or an edge to see the protocol, direction, effect, and consequence.
Mermaid export
flowchart TB start["1 Need live updates?"] bi["2 Bidirectional?"] br["3 Browser UI?"] sse["4 Prefer SSE"] start -->|1 Need live updates?| bi bi -->|no| sse bi -->|yes| br
One-way — SSE unless a hostile proxy strips streaming / Upgrade:
Decisions
- 1
4 Prefer SSE
- next7 Hostile proxy?
- ?
7 Hostile proxy?
- strips streaming / Upgrade8 Long-poll fallback
- ok9 Stay on SSE
- 3
8 Long-poll fallback
- 4
9 Stay on SSE
Bidirectional — WebSocket in the browser, MQTT on IoT or native. Bridge to Kafka only when replay is a product requirement:
Decisions
- ?
3 Browser UI?
- yes5 WebSocket
- no IoT or native6 MQTT
- 2
5 WebSocket
- next10 Need durable replay?
- 3
6 MQTT
- next10 Need durable replay?
- ?
10 Need durable replay?
- yes11 Bridge to Kafka
- no12 Done
- 5
11 Bridge to Kafka
- 6
12 Done
The diagrams deliberately do not loop SSE back onto itself (a labeled self-loop next to other labeled edges shrinks desktop fonts). Hostile-proxy "ok" is a separate stay-on-SSE node. Each chooser fence is a single-column TB flow so desktop labels stay at theme size.
Sandbox: chooser (Python)
Press Run. Snippets must be self-contained — no network, files, or native modules.
Same idea (TypeScript)
Press Run. Snippets must be self-contained — no network, files, or native modules.
Anti-patterns
- Using WebSocket only to tunnel REST request/response — prefer HTTP unless you need push.
- MQTT shared subscription assumed to equal Kafka partition assignment — ordering and rebalance differ.
- SSE for binary file transfer — wrong tool; use HTTP download.
- Long-polling with zero jitter — synchronized reconnect storms after deploys.
- Dual-writing WS and MQTT without an idempotency key — clients see duplicates.
Migration story (interview narrative)
Start with SSE for a notification bell. Add client→server actions via REST. When you need presence and typing indicators, upgrade the notification channel to WebSocket. If you later onboard IoT sensors, introduce MQTT and bridge high-value events into the same fan-out bus or Kafka for analytics — without rewriting the browser path.
Pitfalls
A product starts as a notification bell, adds typing indicators, then adds factory sensors and a 90-day audit log. Name the protocol at each stage and what you refuse to rip out. Now the enterprise customer sits behind a proxy that strips Upgrade — where does long-polling enter, and what do you tell them about latency?
Interview Q&A
SSE vs WebSocket for stock tickers?
Answer
SSE is often enough (server→client). WebSocket if users place orders on the same channel. Many desks still POST orders over HTTP and SSE the ticks.
Why HTTP/2 helps SSE?
Answer
Multiplexing avoids the per-host connection caps of HTTP/1.1 (browsers historically ~6). Without it, a dashboard plus a few EventSources starves other tabs on the same origin.
Long-polling herd?
Answer
Jitter timeouts. Cache ETag / Last-Modified so empty polls stay cheap. Stagger reconnect after deploys the same way you stagger WebSocket 1001.
MQTT in the browser?
Answer
MQTT over WebSocket to the broker. Topics and QoS still apply. Edge scaling still looks like WebSockets: idle timeouts, sticky or a bus.
Replace Kafka with MQTT QoS 2?
Answer
No. Different durability and consumer model. Bridge if you need replay, consumer groups, or stream processing. Depth: Kafka delivery.
Socket.IO default?
Answer
May start with polling then upgrade. Measure cold-start cost and what the load balancer actually sees. Depth: handshake.
Mobile battery?
Answer
MQTT persistent session plus a longer keepalive is often gentler than a chatty WebSocket. Presence can use LWT instead of a heartbeat storm. Depth: MQTT sessions.
Auth difference?
Answer
WebSocket often cookie or Authorization header on the upgrade. MQTT uses CONNECT username/password, JWT plugins, or mTLS at the broker. Depth: brokers.
When is WebSocket the wrong chat default?
Answer
When the UI is one-way, the client is an MCU, or the product is topic ACL across tenants. Also when you only needed HTTP POST plus SSE.
Can SSE resume?
Answer
Yes — Last-Event-ID. The server should store a short ring of ids, not an infinite log. For a real replay API, you wanted Kafka (or similar) anyway.
Dual-write WS and MQTT?
Answer
Give events an id. Otherwise the browser socket and the mobile MQTT client both show the same message twice. Idempotency is an application concern on every hop.
Does sticky matter for SSE?
Answer
SSE is still a long-lived HTTP connection pinned to a process. For HA, either drain carefully or share cursor state. Depth: sticky sessions.