How to use Socket.io with Node Clusters
Node.js is an efficient and popular server-side JavaScript runtime that allows developers to build scalable and high-performance applications. Node.js provides the ability to create multiple processes or "clusters" to take advantage of multi-core CPUs and distribute the load across them.
However, using Node clusters with Socket.io can be a bit tricky, especially when it comes to handling client connections and broadcasting events. In this article, we will explore how to use Socket.io with Node clusters to build scalable real-time applications.

Understanding Node Clusters
Node clusters allow you to create multiple worker processes that can share the same port and handle incoming requests. Clustering is a powerful technique that allows you to take advantage of multi-core CPUs and distribute the load across them.
To create a cluster in Node.js, you can use the built-in cluster module. The cluster module provides a way to spawn child processes that share server ports with the parent process. Each child process in the cluster is referred to as a worker.
Here's an example of creating a Node cluster:
const cluster = require('cluster');const http = require('http');const numCPUs = require('os').cpus().length;if (cluster.isMaster) {console.log(`Master ${process.pid} is running`);// Fork workers.for (let i = 0; i < numCPUs; i++) {cluster.fork();}cluster.on('exit', (worker, code, signal) => {console.log(`worker ${worker.process.pid} died`);});} else {// Worker processconsole.log(`Worker ${process.pid} started`);const server = http.createServer((req, res) => {res.writeHead(200);res.end('hello world\n');});server.listen(3000, () => {console.log(`Server running at http://localhost:3000/`);});}
In this example, we first check if the current process is the master process using the isMaster property. If it is, we create multiple worker processes using the fork() method. We also listen for the exit event on the cluster object to handle worker process failures.
If the current process is not the master process, we create an HTTP server using the http module and listen on port 3000. Each worker process will have its own instance of the server and will share the same port.
Using Socket.io with Node Clusters
To use Socket.io with Node clusters, we need to make sure that client connections are distributed evenly among the worker processes. We also need to ensure that messages are broadcasted to all connected clients, regardless of the worker process they are connected to.
To achieve this, we need to use a shared state between the worker processes. There are several approaches to implement shared state, including using an external cache or database. However, in this article, we will use the sticky-session module, which allows us to use sticky sessions to route client connections to the same worker process.
sticky-session module creates a middleware function that generates a hash based on the IP address and port of the client socket. This hash is then used to route the socket connection to the same worker process on subsequent requests.
Here's an example of using sticky-session with Socket.io:
const cluster = require('cluster');const numCPUs = require('os').cpus().length;if (cluster.isMaster) {// ...} else {const server = require('http').createServer();const io = require('socket.io')(server);const sticky = require('sticky-session');io.on('connection', (socket) => {console.log(`Worker ${cluster.worker.id} handling socket connection`);socket.on('chat message', (msg) => {console.log(`Worker ${cluster.worker.id} received message: ${msg}`);io.emit('chat message', msg);});});sticky.listen(server, 3000);console.log(`Worker ${cluster.worker.id} started`);}
In this example, we first create a HTTP server using the http module and initialize Socket.io with it. We then create a sticky middleware using the sticky-session module and pass the server instance to it.
Next, we listen for the connection event on the io object to handle incoming socket connections. We log the worker process that's handling the connection and register an event listener for the chat message event. When a client sends a message, we log it and emit the message to all connected clients using the io.emit() method.
Finally, we start the server using the sticky.listen() method and log the worker process that's handling the connection.
With this setup, client connections will be evenly distributed among the worker processes using sticky sessions. Messages broadcasted using Socket.io will be sent to all connected clients, regardless of the worker process they are connected to.
Conclusion
In this article, we explored how to use Socket.io with Node clusters to build scalable real-time applications. We learned how to create a Node cluster using the built-in cluster module and how to use the sticky-session module to route client connections to the same worker process.
Using Node clusters with Socket.io can be challenging, but with the right setup, you can build high-performance real-time applications that can handle a large number of concurrent connections.
Enjoyed this post? Read the next one ↗