WeBuildCrew
💬 Web Development

Building a Real-time Chat System in Next.js

Live chat, presence and notifications feel magical and trip up many teams. Here's a clean, scalable way to build real-time features in a Next.js app with Socket.IO.

WeBuildCrew Team9 min read
#Realtime#Socket.IO#Next.js#WebSockets#Architecture
💬WeBuildCrew

Real-time features — chat, live presence, instant notifications — make a product feel alive. They also catch teams out, because the request/response model most apps use doesn't fit. Here's the clean approach we use to add real-time to a Next.js product without the pain.

1. Why you need a socket layer

Normal HTTP is one-shot: the client asks, the server answers. Chat needs the server to push to clients at any time. That's a persistent connection — WebSockets — and Socket.IO makes them reliable with fallbacks and reconnection built in.

2. The server: rooms and broadcasts

server/socket.ts
TypeScript
import { Server } from "socket.io"; const io = new Server(4000, { cors: { origin: process.env.APP_URL } }); io.on("connection", (socket) => {  socket.on("join", (roomId) => socket.join(roomId));   socket.on("message", async ({ roomId, text, userId }) => {    const msg = await saveMessage({ roomId, text, userId });    io.to(roomId).emit("message", msg); // push to everyone in the room  });});
A dedicated Socket.IO server — rooms scope messages to the right conversation.

3. The client: a tiny hook

hooks/useChat.ts
TypeScript
import { useEffect, useState } from "react";import { io } from "socket.io-client"; const socket = io(process.env.NEXT_PUBLIC_SOCKET_URL!); export function useChat(roomId: string) {  const [messages, setMessages] = useState([]);  useEffect(() => {    socket.emit("join", roomId);    socket.on("message", (m) => setMessages((p) => [...p, m]));    return () => { socket.off("message"); };  }, [roomId]);   const send = (text, userId) => socket.emit("message", { roomId, text, userId });  return { messages, send };}
A reusable hook keeps the socket logic out of your components.

4. Scaling it

  • Persist messages to the database (don't trust memory)
  • Use a Redis adapter so multiple server instances share events
  • Add presence (online/typing) via lightweight events
  • Authenticate the socket connection, not just the page
Estimated timeline
2–6 weeks
Best for
Chat, support, collaboration, live data
Related service
Real-time Applications

Need this built? Explore our Real-time Applications service.

View service →

Written by WeBuildCrew Team · Published 10 January 2026 · 9 min read

FAQ

Frequently asked questions

Can't Next.js do real-time on its own?

Next.js serverless functions aren't ideal for long-lived connections. We run a dedicated Socket.IO (or similar) service alongside the app for reliable real-time.

Do messages survive a refresh or restart?

Yes — we persist messages to the database and load history on join, so nothing is lost.

How does it scale to many users?

With a Redis adapter, multiple server instances share events, so it scales horizontally behind a load balancer.

Keep reading

Related articles

Add real-time features

Live chat, presence and instant notifications — built to scale on a clean socket architecture.