When the Server Needs to Talk Back
"HTTP was designed for fetching documents, not for interactive applications. Every technique in this deck is a workaround for this single constraint."
CSE 135 — Full Overview | Review Questions
The client asks, the server answers — and that's it.
HTTP is like postal mail: you send a letter (request), wait for a reply (response), and the post office has no way to deliver a letter you didn't ask for. A telephone is bidirectional — HTTP is not.
Eight scenarios where the server knows something the client doesn't.
| Scenario | Why Request-Response Fails | What's Needed |
|---|---|---|
| Chat / messaging | Messages arrive from other users; your client doesn't know | Instant delivery |
| Live scores | Scores change continuously; client shows stale data | Continuous updates |
| Notifications | Server-side events happen unpredictably | Push when event occurs |
| Collaborative editing | Multiple users change the same document | Bidirectional real-time sync |
| Progress indicators | Server-side task running; client wants updates | Server pushes progress |
| Multiplayer games | Other players' actions must appear immediately | Low-latency bidirectional |
| IoT / dashboards | Sensor data streams in continuously | Continuous data feed |
| Financial trading | Sub-second price changes; stale data costs money | Lowest latency updates |
The simplest workaround: ask repeatedly on a timer.
setInterval + fetch.Server holds the connection open until it has something to say.
HTTP's built-in push mechanism — a response that never ends.
SSE is unidirectional (server → client). The client uses regular fetch to send data back. The browser's EventSource API handles reconnection automatically, including resuming from the last event ID.
EventSource API handles reconnection automatically. For server-to-client push, SSE is often all you need.
| Field | Purpose | Example |
|---|---|---|
data: | Event payload (can span multiple lines) | data: {"score": 42} |
event: | Named event type (triggers specific listeners) | event: notification |
id: | Event ID for reconnection (browser sends Last-Event-ID) | id: 1001 |
retry: | Reconnection interval in milliseconds | retry: 5000 |
Built-in reconnection: If the connection drops, the browser automatically reconnects and sends Last-Event-ID. The server resumes from where it left off — no client-side reconnection logic needed.
Full-duplex bidirectional communication — the only browser API where both sides talk freely.
Start simple. Upgrade when you hit limits, not before.
| Aspect | Polling | Long Polling | SSE | WebSockets |
|---|---|---|---|---|
| Direction | Client → Server | Client → Server | Server → Client | Bidirectional |
| Protocol | HTTP | HTTP | HTTP | WS (after upgrade) |
| Connection | New each time | Held, re-established | Single persistent HTTP | Single persistent WS |
| Latency | 0 to N sec (avg N/2) | Near-instant | Near-instant | Near-instant |
| Server load | High (constant) | Moderate (held) | Low (1 per client) | Low (1 per client) |
| Bandwidth | High (HTTP overhead) | Moderate | Low | Very low |
| Client complexity | Very low | Low | Very low (EventSource) | Moderate |
| Server complexity | Very low | Moderate | Moderate | High |
| Auto-reconnect | N/A | Manual | Built-in | Manual |
| Proxy/firewall | Works everywhere | Works everywhere | Usually works | May be blocked |
| Scalability | Poor at high freq | Moderate | Good | Good (but stateful) |
| Best for | Low-freq checks | Moderate real-time | Push: feeds, progress | Chat, games, collab |
Production is messier than tutorials — proxies, firewalls, and mobile networks.
| Technique | Corporate Proxy | CDN | Mobile Carrier | Load Balancer |
|---|---|---|---|---|
| Polling | Works | Works (cacheable) | Works | Works |
| Long Polling | Works (may timeout) | Works (not cacheable) | Works (may timeout) | Works |
| SSE | May buffer/break | May buffer | May buffer | Needs config |
| WebSockets | May block upgrade | Requires WS support | Usually works | Needs sticky sessions |
Corporate proxies are especially problematic: SSL inspection (MITM), buffered streaming responses, blocked Upgrade headers. HTTPS mitigates many of these issues.
| Challenge | Mechanism | Solution |
|---|---|---|
| NAT timeout | Carriers kill idle TCP after 30–60s | Heartbeat pings every 15–30s |
| Network switching | WiFi → cellular drops all TCP | Auto-reconnect with exponential backoff |
| Battery drain | Persistent connections prevent radio sleep | Reduce ping frequency; batch updates |
Socket.IO tries WebSocket first, detects failure, and falls back to long polling — transparently. The application code doesn't change.
Newer technologies addressing WebSocket limitations.
subscription { newMessage { text, author } } and the server pushes matching data.10 concepts of real-time web communication in one table.
| Concept | Key Takeaway |
|---|---|
| The Problem | HTTP is request-response only. The server cannot contact the client — every real-time technique is a workaround. |
| When You Need More | Chat, live scores, notifications, collaboration, games, trading — the server knows something the client doesn't. |
| Polling | Client asks repeatedly on a timer. Simple and universal, but wastes bandwidth. Fine for low-frequency updates. |
| Long Polling | Server holds connection until it has data. Near-instant delivery, still just HTTP, but holds connections open. |
| SSE | Standardized HTTP streaming. EventSource API with built-in reconnection. Unidirectional (server → client). |
| WebSockets | Full-duplex bidirectional. Starts as HTTP, upgrades to WS. Stateful and harder to scale. |
| Choosing | Start simple. Polling for infrequent. SSE for push. WebSockets only for true bidirectional needs. |
| Infrastructure | Proxies buffer SSE, firewalls block WS upgrades. Polling works everywhere. Always have a fallback. |
| The Future | WebTransport, HTTP/3, GraphQL Subscriptions, gRPC Streaming — same core idea, different protocols. |