Introduction to Real-Time Web
Understand real-time communication on the web, its importance, and different technologies available
What is Real-Time Communication?
Real-time communication enables instant data exchange between clients and servers (or directly between clients) without the traditional request-response delay. Instead of users manually refreshing pages, updates appear instantly—like magic.
Think about your favorite apps: chat messages appearing instantly, stock prices updating live, multiplayer games synchronizing player positions, or collaborative documents showing other users' cursors in real-time. All of these rely on real-time web technologies.
🎯 Real-Time Use Cases
Communication
- • Chat applications (Slack, Discord)
- • Video conferencing (Zoom, Google Meet)
- • Notifications and alerts
Collaboration
- • Document editing (Google Docs, Figma)
- • Whiteboarding tools
- • Multiplayer games
Live Data
- • Stock tickers and trading
- • Sports scores and live events
- • IoT dashboards
Social
- • Live streaming (Twitch, YouTube Live)
- • Social feeds and reactions
- • Presence indicators (online/typing)
The Evolution: From Polling to Push
Understanding how we got to modern real-time is crucial. Let's trace the evolution:
1. Traditional HTTP Request-Response
// The classic model - client always initiates
// User clicks "Refresh" or waits for page reload
fetch('/api/messages')
.then(res => res.json())
.then(messages => updateUI(messages));
// Problem: No way for server to notify client of new data!
In traditional HTTP, the client must always initiate communication. The server cannot "push" data to the client—it can only respond to requests.
2. Short Polling
// Short polling - repeatedly ask "anything new?"
function pollForUpdates() {
setInterval(async () => {
const response = await fetch('/api/messages?since=' + lastTimestamp);
const newMessages = await response.json();
if (newMessages.length > 0) {
lastTimestamp = newMessages[newMessages.length - 1].timestamp;
displayMessages(newMessages);
}
}, 3000); // Check every 3 seconds
}
// Problems:
// - Wastes bandwidth (mostly empty responses)
// - Wastes server resources (constant requests)
// - Not truly real-time (up to 3 second delay)
// - Battery drain on mobile devices
3. Long Polling
// Long polling - "hold my request until you have something"
async function longPoll() {
while (true) {
try {
// This request stays open until server has new data
// or timeout occurs (usually 30-60 seconds)
const response = await fetch('/api/messages/subscribe', {
timeout: 60000
});
const messages = await response.json();
displayMessages(messages);
} catch (error) {
// Reconnect on error or timeout
await sleep(1000);
}
}
}
// Better than short polling:
// ✓ Near real-time updates
// ✓ Less wasted requests
//
// Still has issues:
// ✗ Each message requires new HTTP connection
// ✗ HTTP overhead on every response
// ✗ Complex server implementation
4. Server-Sent Events (SSE)
// SSE - server can push text data to client
const eventSource = new EventSource('/api/events');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
displayMessage(data);
};
eventSource.onerror = (error) => {
console.error('SSE error:', error);
// EventSource auto-reconnects!
};
// Advantages:
// ✓ Simple API (built into browsers)
// ✓ Automatic reconnection
// ✓ Works over HTTP/2
//
// Limitations:
// ✗ One-way only (server → client)
// ✗ Text-based (no binary)
// ✗ Limited browser connections per domain
5. WebSockets
// WebSocket - full-duplex, persistent connection
const socket = new WebSocket('wss://api.example.com/ws');
socket.onopen = () => {
console.log('Connected!');
socket.send(JSON.stringify({ type: 'subscribe', channel: 'chat' }));
};
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
displayMessage(message);
};
// Send messages anytime!
function sendMessage(text) {
socket.send(JSON.stringify({ type: 'message', text }));
}
// Advantages:
// ✓ Full duplex (bidirectional)
// ✓ Low latency (no HTTP overhead per message)
// ✓ Binary and text support
// ✓ Efficient for high-frequency updates
6. WebRTC
// WebRTC - peer-to-peer, no server in the middle!
const peerConnection = new RTCPeerConnection(config);
// Get local video/audio
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
// Add tracks to peer connection
stream.getTracks().forEach(track => {
peerConnection.addTrack(track, stream);
});
// Listen for remote tracks
peerConnection.ontrack = (event) => {
remoteVideo.srcObject = event.streams[0];
};
// Advantages:
// ✓ Direct peer-to-peer (lowest possible latency)
// ✓ No server bandwidth for media
// ✓ Video, audio, and arbitrary data
//
// Complexity:
// ✗ Requires signaling server for connection setup
// ✗ NAT traversal challenges
// ✗ More complex API
Technology Comparison
| Technology | Direction | Protocol | Best For |
|---|---|---|---|
| Polling | Client → Server | HTTP | Legacy systems, simple updates |
| Long Polling | Server → Client | HTTP | Fallback, behind proxies |
| SSE | Server → Client | HTTP | News feeds, notifications |
| WebSocket | Bidirectional | WS/WSS | Chat, gaming, collaboration |
| WebRTC | Peer-to-Peer | UDP/SCTP | Video calls, file sharing |
Choosing the Right Technology
// Decision tree for real-time technology choice:
function chooseRealtimeTech(requirements) {
// Need peer-to-peer media/video?
if (requirements.peerToPeer || requirements.videoStreaming) {
return 'WebRTC';
}
// Need bidirectional communication?
if (requirements.clientToServer && requirements.serverToClient) {
// High frequency updates or gaming?
if (requirements.highFrequency || requirements.gaming) {
return 'WebSocket';
}
// Moderate updates with fallback needs?
return 'Socket.io'; // Handles fallbacks automatically
}
// Only server → client updates?
if (requirements.serverToClient) {
// Simple notifications/feeds?
if (requirements.simple && !requirements.binary) {
return 'SSE'; // Simplest API, auto-reconnect
}
return 'WebSocket';
}
// Infrequent updates, simplicity preferred?
if (requirements.infrequent) {
return 'Long Polling';
}
return 'WebSocket'; // Safe default
}
⚠️ Real-Time Challenges
Connection Management
- • Handling disconnections gracefully
- • Reconnection with exponential backoff
- • State synchronization after reconnect
Scaling
- • Each connection consumes server memory
- • Broadcasting across multiple servers
- • Connection limits per server
Security
- • Authentication for persistent connections
- • Rate limiting messages
- • Validating all incoming data
Network Issues
- • NAT traversal (especially WebRTC)
- • Firewall and proxy restrictions
- • Mobile network switching
💡 What You'll Learn in This Course
- ✓ WebSocket Protocol - Deep dive into handshake, frames, and lifecycle
- ✓ Building Servers - Create WebSocket servers in Node.js
- ✓ Socket.io - Use the most popular real-time library
- ✓ Server-Sent Events - Simple one-way streaming
- ✓ WebRTC Architecture - Understand peer-to-peer connections
- ✓ Signaling Servers - Connect peers across the internet
- ✓ Video Streaming - Build video call applications
- ✓ Design Patterns - Scale real-time applications