Back to Blog
Engineering5 min read

Building Real-Time Features with WebSockets in Next.js

When You Need Real-Time

Polling is simple and often good enough: check for updates every 30 seconds. But for features where latency matters — chat, live dashboards, collaborative editing, real-time notifications — WebSockets are the right tool. They maintain a persistent connection, allowing the server to push updates to clients instantly.

The Architecture Problem with Next.js

Next.js API routes are stateless serverless functions. Each request spins up a new function instance, which means you cannot maintain WebSocket connections in API routes. The solution is to run a separate Node.js server alongside your Next.js app, or use a managed WebSocket service like Ably, Pusher, or Soketi (self-hosted).

Option 1: Separate Socket.io Server

Run a Node.js + Socket.io server on a separate port (or subdomain). Next.js communicates with it via HTTP for internal operations, and clients connect directly for WebSocket subscriptions. This is the most flexible approach and works well on Railway, Render, or any containerized deployment.

// server.ts — standalone Socket.io server
import { Server } from "socket.io";
const io = new Server(3001, { cors: { origin: process.env.NEXT_PUBLIC_APP_URL } });

io.on("connection", (socket) => {
  socket.on("join-room", (roomId) => socket.join(roomId));
  socket.on("update", (data) => io.to(data.roomId).emit("update", data));
});

Option 2: Managed WebSocket Service

For teams that do not want to manage WebSocket infrastructure, Ably and Pusher handle connections, scaling, and delivery guarantees. Your Next.js app publishes events to their API, and clients subscribe via their SDK. Simpler to operate, costs money at scale, but gets you to production faster.

Option 3: Vercel + Upstash + SSE

Server-Sent Events (SSE) are a simpler alternative for one-directional updates (server → client). Next.js supports SSE natively via streaming responses. Combine with Upstash Redis pub/sub to fan out events across multiple serverless function instances. Works on Vercel with no additional infrastructure.

Practical Considerations

Always implement reconnection logic on the client — networks drop, servers restart. Socket.io handles this automatically. For collaborative features, use operational transforms or CRDTs (conflict-free replicated data types) to handle concurrent edits without conflicts. Libraries like Yjs make this manageable.

I have built real-time dashboards, live chat systems, and collaborative tools on Next.js. Reach out if you are adding real-time features to your product.

Next.jsWebSocketsReal-TimeNode.js

Hire me for similar projects

Looking for a developer who can build what you just read about? Let's talk.

Get in Touch