WeBuildCrew
Web Development

Real-time Features in Web Apps: WebSockets, SSE & Live Updates

When to use WebSockets vs Server-Sent Events vs polling — and how to build live notifications, presence indicators and collaborative features that actually scale.

Zahid Ghotia7 min read
#Real-time Applications#WebSockets#Real-time Web Development#Socket.IO#Next.js#Live Features
Real-time Features in Web Apps: WebSockets, SSE & Live UpdatesWeBuildCrew

Every modern app eventually needs something live: a notification badge, a chat message, a presence indicator, a progress bar. The wrong choice here creates scaling headaches. This guide is a practical map to the three main approaches and when each one is right.

WebSockets vs SSE vs polling

Three tools, three tradeoffs:

  • WebSockets: bidirectional, both sides send/receive — right for chat, multiplayer, collaborative editors.
  • SSE (Server-Sent Events): server pushes, client reads — right for notifications, live dashboards, progress bars.
  • Polling: client asks repeatedly — right for simple cases where real-time is nice-to-have, not critical.

SSE in Next.js App Router

app/api/events/route.ts
TypeScript
export async function GET(req: Request) {  const encoder = new TextEncoder();  const stream = new ReadableStream({    async start(controller) {      const send = (data: object) =>        controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`));       // Send current state immediately      send({ type: "init", unread: await getUnreadCount(req) });       // Poll for changes (replace with pub/sub in production)      const interval = setInterval(async () => {        const count = await getUnreadCount(req);        send({ type: "update", unread: count });      }, 5000);       req.signal.addEventListener("abort", () => {        clearInterval(interval);        controller.close();      });    },  });  return new Response(stream, {    headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" },  });}
Streaming SSE route — client receives updates via EventSource.

WebSockets for chat

For chat or collaborative features, Socket.IO (or raw ws) with a Redis Pub/Sub adapter is the production pattern. Every server instance subscribes to a shared Redis channel — so a message sent to server A is broadcast to clients on server B.

Presence indicators

Presence (the green dot showing who's online) uses Redis with short-lived keys: a client sends a heartbeat every 30 seconds, the server writes `user:{id}:online` with a 60-second TTL. A presence API returns all keys matching the pattern.

SSE

Server push

WS

Bidirectional

Redis

Pub/sub scale

< 50ms

Event latency

Need this built? Explore our SaaS Development service.

View service →

Written by Zahid Ghotia · Published 18 June 2026 · 7 min read

FAQ

Frequently asked questions

Does SSE work with Vercel?

Yes — Vercel supports streaming responses. For long-lived connections at scale, an edge worker or dedicated server is more cost-effective.

How does real-time work with Next.js Server Components?

Server Components run once on the server. Real-time requires a Client Component with useEffect and EventSource (for SSE) or a socket library.

How do I scale WebSockets?

Socket.IO with the Redis adapter — all server instances share state via a pub/sub channel, so messages route correctly regardless of which server the client is connected to.

Can you add real-time to an existing app?

Yes — we add real-time as a layer on top of existing REST APIs, with no disruption to non-realtime flows.

Keep reading

Related articles

Add real-time to your app

Live notifications, chat, presence and collaborative features built to scale.