Episode ini membahas menskalakan Socket.IO ke banyak server: masalah sinkronisasi lintas instance, pola pub-sub Redis, pemasangan Redis adapter, alternatif adapter lain, dan pola arsitektur untuk server stateless.

Di episode 15 kalian meletakkan beberapa server di belakang load balancer. Tapi ada masalah besar: jika klien di server A mengirim pesan ke room, klien di server B tidak akan menerimanya — karena room hanya dikenal di memori server A.
Episode 16 membahas solusinya: Redis adapter. Dengan pola publish-subscribe, setiap instance Socket.IO menyebarkan event ke semua instance lain, sehingga room, namespace, dan broadcast bekerja seolah-olah satu server.
Socket.IO menyimpan room dan koneksi di memori setiap instance. Saat instance berbeda, informasi ini tidak saling melihat.
// instance A
io.to("game-1").emit("status", "dimulai");
// klien di instance B tidak menerima apa punio.to("game-1").emit(...) di instance A hanya menjangkau koneksi yang ada di memori instance A. Koneksi di instance B buta terhadap event ini. State seperti ini disebut state lokal atau in-memory state.
Semua instance harus berbagi informasi melalui penyimpanan bersama. Untuk broadcast real-time, mediumnya bukan database biasa — butuh sesuatu yang sangat cepat dengan pola publish-subscribe. Di situlah Redis masuk.
Redis Pub/Sub adalah pola satu-penerbit-banyak-pelanggan yang sangat sederhana.
const redis = require("redis");
const publisher = redis.createClient();
const subscriber = redis.createClient();
await subscriber.subscribe("saluran:game", (pesan) => {
console.log("diterima:", pesan);
});
await publisher.publish("saluran:game", "event baru");subscriber.subscribe(channel, fn) mendaftarkan pemanggil untuk saluran tertentu, dan publisher.publish(channel, pesan) menyebarkan pesan ke semua pelanggan saluran itu. Redis meneruskan pesan secepat mungkin tanpa menyimpannya.
Database menulis dan membaca dengan query — terlalu lambat untuk event real-time. Pub/Sub Redis mengirim pesan secara langsung ke pelanggan dalam mikrodetik. Trade-off-nya: pesan Pub/Sub hilang jika tidak ada pelanggan, jadi hanya cocok untuk event real-time, bukan untuk persistence.
Adapter mengubah Socket.IO sehingga broadcast dikirim lewat Redis.
bun add @socket.io/redis-adapter redisconst { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");
const pubClient = createClient({ url: "redis://redis:6379" });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
const io = new Server(server, {
adapter: createAdapter(pubClient, subClient),
});createAdapter(pubClient, subClient) membutuhkan dua koneksi Redis: satu untuk publish, satu untuk subscribe. Dengan adapter ini, io.to("game-1").emit(...) di instance mana pun akan disebar ke semua instance yang terhubung Redis yang sama.
Setelah adapter terpasang, fitur berikut bekerja lintas instance tanpa perubahan kode:
Kode aplikasi kalian tidak berubah — adapter bekerja transparan di bawah Socket.IO.
Untuk Redis cluster dengan banyak node, gunakan konfigurasi khusus.
const { createCluster } = require("redis");
const { createClusterAdapter } = require("@socket.io/redis-adapter");
const redis = createCluster({
rootNodes: [
{ url: "redis://redis-1:6379" },
{ url: "redis://redis-2:6379" },
],
});createClusterAdapter(...) menangani banyak node Redis sekaligus. Ini berguna saat volume event sudah melebihi kapasitas satu Redis.
Beberapa adapter lain tersedia untuk kebutuhan berbeda.
MongoDB : memakai change stream, cocok saat Mongo sudah jadi basis utama
RabbitMQ : memakai exchange fanout, bagus untuk integrasi broker yang ada
Kafka : memakai topic, untuk event log berskala besarPilih adapter berdasarkan infrastruktur yang sudah dimiliki tim. Redis tetap paling populer karena ringan, cepat, dan mudah dipasang. Semua adapter mengimplementasikan antarmuka yang sama, jadi menggantinya tidak mengubah kode aplikasi.
Dengan adapter, server menjadi hampir stateless: semua state koneksi berbagi lewat Redis.
const io = new Server(server, {
adapter: createAdapter(pubClient, subClient),
});Kode yang sama dijalankan di berapa pun instance. Menambah instance tinggal menjalankan container yang sama dan mendaftarkannya ke load balancer — tidak ada konfigurasi khusus per instance.
Beberapa hal masih perlu perhatian:
Episode 16 membuka jalan menuju skala horizontal: dengan Redis adapter, room dan broadcast tidak lagi terbatas pada satu instance, dan server bisa ditambah sesuka hati tanpa mengubah kode.
Inti yang harus dibawa pulang:
Di episode 17 berikutnya kita membahas performance optimization: optimasi koneksi dan pesan, clustering Node.js, pengaturan event loop, serta optimasi jaringan dan klien.