Kemarin saya lagi bikin fitur live notification untuk salah satu aplikasi. Awalnya pakai polling biasa, request ke server setiap 5 detik. Works fine buat 10 user. Tapi begitu user naik ke 200+, server langsung ngos-ngosan. CPU usage merangkak naik, dan response time jadi lambat. Saat itulah saya sadar: untuk real-time data, polling itu jawaban yang salah.
Polling itu kayak kamu nelpon teman setiap 5 detik nanya "udah sampe rumah belum?". Bayangin kalau 200 orang nelpon kamu dengan pertanyaan yang sama. Itu yang terjadi di server kamu. WebSocket solusinya. Bukannya kamu nelpon, teman kamu yang langsung nelpon begitu sampe. Efisien, cepat, dan nggak bikin server kelebihan beban.
WebSocket adalah protokol komunikasi yang memungkinkan koneksi dua arah (full-duplex) antara browser dan server lewat satu koneksi TCP yang persisten. Berbeda dengan HTTP yang request-response (client minta, server jawab, koneksi tutup), WebSocket bikin koneksi terbuka terus-menerus. Server bisa kirim data ke client kapan saja tanpa menunggu request.
Dibandingkan dengan HTTP polling yang bikin server kewalahan, WebSocket punya beberapa keunggulan utama:
Alurnya cukup sederhana. Pertama, client (browser) mengirim HTTP request dengan header Upgrade: websocket. Ini namanya WebSocket handshake. Kalau server mendukung WebSocket, dia jawab dengan status 101 Switching Protocols. Setelah itu, koneksi HTTP tadi di-upgrade jadi koneksi WebSocket. Dari titik ini, baik client maupun server bisa saling kirim pesan kapan saja.
Yang menarik, WebSocket bukan ganti HTTP. Mereka berjalan di atas TCP, sama seperti HTTP. Port yang dipakai juga sama (80 untuk ws:// dan 443 untuk wss://). Jadi kamu nggak perlu buka port baru di firewall.
Mari kita bikin WebSocket server sederhana pakai library ws untuk Node.js. Ini library paling populer dan ringan untuk WebSocket di ekosistem JavaScript.
Pertama, install dependency-nya:
mkdir websocket-demo && cd websocket-demo
npm init -y
npm install ws express
Lalu bikin server-nya:
const express = require('express');
const { WebSocketServer } = require('ws');
const http = require('http');
const app = express();
const server = http.createServer(app);
const wss = new WebSocketServer({ server });
// Simpan semua client yang terkoneksi
const clients = new Set();
wss.on('connection', (ws, req) => {
const clientId = Date.now();
console.log(`Client connected: ${clientId}`);
clients.add(ws);
// Kirim pesan welcome
ws.send(JSON.stringify({
type: 'welcome',
message: `Halo! ID kamu adalah ${clientId}`,
onlineCount: clients.size
}));
// Broadcast ke semua client bahwa user baru join
broadcast({
type: 'user_joined',
onlineCount: clients.size
}, ws);
// Terima pesan dari client
ws.on('message', (data) => {
try {
const msg = JSON.parse(data.toString());
console.log(`Pesan dari ${clientId}:`, msg);
// Broadcast pesan ke semua client
broadcast({
type: 'message',
sender: clientId,
text: msg.text,
timestamp: new Date().toISOString()
});
} catch (e) {
console.error('Parse error:', e.message);
}
});
// Handle disconnect
ws.on('close', () => {
clients.delete(ws);
broadcast({
type: 'user_left',
onlineCount: clients.size
});
console.log(`Client disconnected: ${clientId}`);
});
});
function broadcast(message, exclude = null) {
const data = JSON.stringify(message);
clients.forEach(client => {
if (client !== exclude && client.readyState === 1) {
client.send(data);
}
});
}
server.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Kode di atas bikin chat server sederhana. Setiap user yang connect akan dapat pesan welcome, dan setiap pesan yang dikirim akan di-broadcast ke semua user yang online.
Di sisi browser, API WebSocket sudah built-in. Kamu nggak perlu library tambahan. Cukup pakai object WebSocket yang sudah ada di semua browser modern.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat Demo</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 50px auto; }
#messages { border: 1px solid #ccc; height: 300px; overflow-y: auto; padding: 10px; margin-bottom: 10px; }
.msg { padding: 5px 0; border-bottom: 1px solid #eee; }
.system { color: #888; font-style: italic; }
input { padding: 8px; width: 70%; }
button { padding: 8px 16px; }
</style>
</head>
<body>
<h2>WebSocket Chat</h2>
<div id="status">Connecting...</div>
<div id="messages"></div>
<input type="text" id="input" placeholder="Ketik pesan...">
<button onclick="send()">Kirim</button>
<script>
const ws = new WebSocket('ws://localhost:3000');
const messages = document.getElementById('messages');
const status = document.getElementById('status');
const input = document.getElementById('input');
ws.onopen = () => {
status.textContent = 'Connected';
status.style.color = 'green';
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
const div = document.createElement('div');
div.className = 'msg' + (msg.type !== 'message' ? ' system' : '');
if (msg.type === 'welcome') {
div.textContent = `[System] ${msg.message} | Online: ${msg.onlineCount}`;
} else if (msg.type === 'user_joined') {
div.textContent = `[System] User joined. Online: ${msg.onlineCount}`;
} else if (msg.type === 'user_left') {
div.textContent = `[System] User left. Online: ${msg.onlineCount}`;
} else if (msg.type === 'message') {
div.textContent = `[${msg.sender}] ${msg.text}`;
}
messages.appendChild(div);
messages.scrollTop = messages.scrollHeight;
};
ws.onclose = () => {
status.textContent = 'Disconnected';
status.style.color = 'red';
};
function send() {
const text = input.value.trim();
if (text && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ text }));
input.value = '';
}
}
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') send();
});
</script>
</body>
</html>
Buka file HTML ini di dua tab browser, dan kamu bisa chat antar tab secara real-time. Coba bayangin bikin ini pakai HTTP polling. Kamu butuh request setiap 1-2 detik untuk dapetin pesan baru. Dengan WebSocket, pesan langsung muncul begitu dikirim.
Kalau kamu butuh fitur lebih advanced seperti auto-reconnect, room management, atau fallback ke polling untuk browser lama, Socket.IO adalah pilihan yang lebih lengkap. Socket.IO itu wrapper di atas WebSocket dengan banyak fitur tambahan.
npm install socket.io socket.io-client
// Server (socket.io)
const { Server } = require('socket.io');
const io = new Server(3000, {
cors: { origin: '*' }
});
io.on('connection', (socket) => {
console.log('User connected:', socket.id);
// Join room
socket.on('join_room', (room) => {
socket.join(room);
socket.to(room).emit('user_joined', socket.id);
});
// Pesan ke room tertentu
socket.on('send_message', (data) => {
socket.to(data.room).emit('receive_message', {
sender: socket.id,
text: data.text,
time: new Date().toISOString()
});
});
socket.on('disconnect', () => {
console.log('User left:', socket.id);
});
});
Socket.IO cocok untuk aplikasi yang butuh reliability tinggi. Tapi untuk kasus sederhana, library ws sudah lebih dari cukup dan lebih ringan.
WebSocket dipakai di banyak aplikasi populer. Beberapa use case yang paling common:
Ngelola koneksi WebSocket di production berbeda dengan development. Berikut beberapa tips yang saya pelajari dari pengalaman:
1. Gunakan load balancer yang support WebSocket. Nginx dan HAProxy mendukung WebSocket, tapi konfigurasinya beda. Pastikan proxy_set_header Upgrade $http_upgrade dan proxy_set_header Connection "upgrade" sudah di-set.
# Nginx config untuk WebSocket
location /ws/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
2. Handle reconnect di client. Koneksi WebSocket bisa putus karena berbagai alasan (network instability, server restart). Client kamu harus bisa auto-reconnect.
function connectWebSocket() {
const ws = new WebSocket('wss://yourserver.com/ws');
ws.onopen = () => { console.log('Connected'); };
ws.onclose = () => {
console.log('Disconnected. Reconnecting in 3s...');
setTimeout(connectWebSocket, 3000);
};
ws.onerror = (err) => {
console.error('WebSocket error:', err);
ws.close();
};
return ws;
}
connectWebSocket();
3. Pakai heartbeat/ping-pong. Beberapa load balancer dan proxy menutup koneksi idle setelah 30-60 detik. Kirim ping periodik untuk keep-alive.
// Server-side heartbeat
setInterval(() => {
wss.clients.forEach(ws => {
if (ws.isAlive === false) return ws.terminate();
ws.isAlive = false;
ws.ping();
});
}, 30000);
// Detect pong
wss.on('connection', (ws) => {
ws.isAlive = true;
ws.on('pong', () => { ws.isAlive = true; });
});
4. Scale dengan Redis pub/sub. Kalau kamu punya multiple server, WebSocket connection di server A nggak bisa kirim pesan ke client yang connect di server B. Pakai Redis sebagai message broker untuk broadcast antar server.
const redis = require('redis');
const pub = redis.createClient();
const sub = redis.createClient();
sub.subscribe('broadcast');
sub.on('message', (channel, message) => {
// Kirim ke semua client di server ini
wss.clients.forEach(ws => ws.send(message));
});
// Saat mau broadcast dari server manapun
function broadcast(message) {
pub.publish('broadcast', JSON.stringify(message));
}
5. Always use wss:// (TLS). Jangan pernah pakai ws:// di production. Koneksi tanpa enkripsi bisa di-intercept. wss:// enkripsi semua data yang lewat, sama seperti HTTPS.
Sering orang bertanya, kapan pakai WebSocket dan kapan pakai SSE? Jawabannya tergantung use case. SSE cocok kalau kamu hanya butuh server push (satu arah, server ke client). Contohnya live feed, notification, stock price. SSE lebih simpel, pakai HTTP biasa, dan auto-reconnect built-in.
WebSocket lebih cocok kalau kamu butuh komunikasi dua arah. Chat, multiplayer game, collaborative editing. Kalau client juga perlu kirim data ke server secara real-time, WebSocket adalah pilihan yang tepat.
Yang perlu diingat, jangan over-engineer. Kalau aplikasi kamu hanya butuh menampilkan data real-time dari server tanpa client mengirim data balik, SSE sudah cukup. Tapi kalau kamu butuh interaksi real-time dua arah, WebSocket adalah cara yang benar.
WebSocket menyelesaikan masalah real-time communication dengan elegan. Dibanding HTTP polling yang bikin server sibuk menerima request kosong, WebSocket bikin koneksi persisten yang efisien. Server bisa push data kapan saja, client bisa kirim data kapan saja, semua lewat satu koneksi.
Dari chat application sampai live dashboard, WebSocket sudah jadi standar untuk fitur real-time di web modern. Dengan library seperti ws atau Socket.IO, implementasinya nggak serumit yang kamu bayangkan. Yang penting ingat: handle reconnect, pakai heartbeat, scale dengan Redis, dan selalu gunakan wss:// di production.
Kamu sudah pernah pakai WebSocket di project? Atau masih pakai polling sampai sekarang? Coba share pengalaman kamu di kolom komentar, siapa tahu ada tips yang bisa kita pelajari bersama.