What Happens When You Type a URL and Press Enter
DNS lookups, TCP and TLS handshakes, HTTP requests, servers, and the browser's rendering pipeline. The whole journey of a web page, explained so it finally clicks.
Read →Live notifications, chat, dashboards and progress bars all need real-time updates, but not all need WebSockets. How each approach works, the trade-offs, and which one fits your feature.
"We need real-time" usually means one of a few things: show a notification when something happens, update a dashboard as numbers change, show progress on a long task, or let users chat. Each can be built several ways, and reaching for WebSockets by default often adds complexity you don't need.
The client asks the server for updates on a timer.
setInterval(async () => {
const res = await fetch('/api/notifications?since=' + lastSeen)
render(await res.json())
}, 15000)
Good for: dashboards that refresh every few seconds or minutes, checking a job's status, low-traffic internal tools. Honestly, polling covers more use cases than people admit.
Long polling is a variation: the server holds the request open until there's something new (or a timeout), then the client immediately asks again. It reduces delay, but has mostly been replaced by SSE.
The server keeps one HTTP response open and pushes events down it. The browser API is built in:
const events = new EventSource('/api/stream')
events.addEventListener('order_update', e => {
render(JSON.parse(e.data))
})
On the server, you send a response with Content-Type: text/event-stream and write lines like:
event: order_update
data: {"id": 991, "status": "shipped"}
Good for: notifications, live feeds, progress updates, streaming AI responses token by token, live scores and prices. Many "real-time" features are really server-to-client only, which makes SSE a great fit.
A persistent, two-way connection. Either side can send messages at any time.
const socket = new WebSocket('wss://example.com/ws')
socket.addEventListener('message', e => render(JSON.parse(e.data)))
socket.send(JSON.stringify({ type: 'chat', text: 'Hello' }))
Good for: chat, multiplayer games, collaborative editing, live cursors, anything where clients send frequent messages too.
| Polling | SSE | WebSockets | |
|---|---|---|---|
| Direction | Client asks | Server → client | Both ways |
| Latency | Up to the interval | Low | Lowest |
| Complexity | Very low | Low | Higher |
| Auto-reconnect | N/A | Built in | Build it yourself |
| Works through typical proxies | Yes | Yes (disable buffering) | Needs upgrade config |
| Serverless friendly | Yes | Depends on platform | Usually needs special support |
proxy_buffering off; or the X-Accel-Buffering: no header). Long-lived connections need longer timeouts. (Nginx reverse proxy config.)LISTEN/NOTIFY, or a message broker) fans events out to every server. (Scaling.)If you'd rather not run real-time infrastructure yourself, managed services handle connections, scaling and fan-out for you. Supabase Realtime, Firebase, Pusher, Ably and similar products let your backend publish events while they manage the sockets. Great for small teams.
Start with the simplest option that meets the requirement. You can upgrade later without changing what users see.
When the client also needs to send frequent messages over the same connection, like chat, multiplayer games or collaborative editing. For server-to-client updates only, SSE is simpler.
No. Polling is simple and reliable, and perfectly fine for updates that can be a few seconds late. It becomes inefficient only with very short intervals and many clients.
Yes, and HTTP/2 removes the old per-domain connection limit that made many SSE streams awkward over HTTP/1.1.
DNS lookups, TCP and TLS handshakes, HTTP requests, servers, and the browser's rendering pipeline. The whole journey of a web page, explained so it finally clicks.
Read →There are dozens of HTTP status codes, but about fifteen cover nearly everything. What each one means, when to return it, and the mix-ups (401 vs 403, 301 vs 302) that confuse everyone.
Read →A, AAAA, CNAME, MX, TXT and NS records in plain English, why DNS changes seem slow, and the troubleshooting commands that tell you what is really going on.
Read →