All posts

Socket.IO: Building Real-Time Apps with Node.js

Saad Takhir · · 0 views

The problem: HTTP can't speak first

With plain HTTP, communication is one-way: the browser asks, the server answers. The server can't just say "hey, a new message arrived."

But that's exactly what chat, live notifications, online games, or real-time order tracking need. Asking the server "anything new?" every second (polling) means extra load and delays.

What is Socket.IO?

Socket.IO is a library for bidirectional, real-time communication between a server and clients (browsers, mobile apps). It runs mostly on top of WebSocket, but gives you much more:

  • Automatic reconnection — if the connection drops, the client reconnects on its own.
  • Fallback transport — if WebSocket isn't available, it falls back to HTTP long-polling.
  • Events — data is sent through named events.
  • Rooms — group users together.
  • Acknowledgements — confirm that a message was received.

⚠️ Socket.IO is not plain WebSocket. A regular WebSocket client can't connect to a Socket.IO server — you need Socket.IO on both sides.

Installation

npm install socket.io          # server
npm install socket.io-client   # frontend

Server

import { createServer } from 'node:http'
import { Server } from 'socket.io'

const httpServer = createServer()
const io = new Server(httpServer, {
  cors: { origin: 'http://localhost:5173' }
})

io.on('connection', (socket) => {
  console.log('New connection:', socket.id)

  socket.on('chat:message', (text) => {
    // To everyone, including the sender
    io.emit('chat:message', { id: socket.id, text })
  })

  socket.on('disconnect', () => {
    console.log('Disconnected:', socket.id)
  })
})

httpServer.listen(3000, () => {
  console.log('Socket server: http://localhost:3000')
})

Client (frontend)

import { io } from 'socket.io-client'

const socket = io('http://localhost:3000')

socket.on('connect', () => {
  console.log('Connected!', socket.id)
})

socket.on('chat:message', (msg) => {
  console.log(`${msg.id}: ${msg.text}`)
})

socket.emit('chat:message', 'Hello, everyone!')

The core idea is simple: emit sends an event, on listens for one. It works the same way on both sides.

Who gets the message?

socket.emit('event', data)            // only this user
io.emit('event', data)                // everyone
socket.broadcast.emit('event', data)  // everyone except the sender
io.to('room-1').emit('event', data)   // only users in the room

Rooms

For example, a separate room for each chat group or each order:

socket.on('room:join', (roomId) => {
  socket.join(roomId)
  socket.to(roomId).emit('room:notice', `${socket.id} joined`)
})

Rooms exist only on the server — clients don't see them, they just receive the messages.

Acknowledgements

To know that a message reached the server and was processed:

// Client
const res = await socket.emitWithAck('order:create', { item: 'Pizza' })
console.log(res.status) // 'ok'

// Server
socket.on('order:create', (order, callback) => {
  // ... save to database
  callback({ status: 'ok' })
})

Where is it used?

  • Chat apps and messengers
  • Order status (cafes, delivery)
  • Live notifications
  • Real-time stats in admin panels
  • Online games and collaborative editing

Key tips

  • Authentication — verify a token on connect: io(url, { auth: { token } }) plus an io.use() middleware on the server.
  • Event names — prefixed names like chat:message and order:update keep your code organized.
  • Multiple servers — once you scale to several servers, you'll need the Redis adapter, otherwise servers won't see each other's clients.
  • Validate input — never trust data from the client; validate it just like in a REST API.

Wrapping up

Socket.IO makes adding real-time features remarkably easy: a few lines of code give you a working chat or live notification system. Start with a small chat app — it's the best way to really understand Socket.IO.

Share · 0 shares
Get in touch