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 anio.use()middleware on the server. - Event names — prefixed names like
chat:messageandorder:updatekeep 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.