Belajar WebSocket - Presence & Heartbeat Mechanisms
Episode 11 of 34

Belajar WebSocket - Presence & Heartbeat Mechanisms

Episode ini membahas menjaga kesehatan koneksi: mekanisme ping-pong, interval heartbeat, deteksi koneksi mati, serta presence pengguna seperti status online, offline, dan terakhir aktif.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Koneksi WebSocket yang tampak sehat bisa saja sudah mati: jaringan putus di tengah jalan, perangkat tidur, atau router dihapus karena tidak ada trafik. Tanpa pengecekan, server tidak akan pernah tahu sampai pengguna mencoba mengirim pesan dan gagal.

Episode 11 membahas heartbeat: mekanisme ping-pong untuk memastikan koneksi hidup, dan presence: pengetahuan server tentang siapa yang online, offline, sibuk, atau sudah lama tidak aktif. Ini fondasi aplikasi seperti chat yang menampilkan status hijau dan titik abu-abu.

Mekanisme Ping-Pong

Frame Kontrol WebSocket

Protokol WebSocket punya frame kontrol ping dan pong. Klien atau server mengirim ping, lawan menjawab pong. Jika tidak ada pong, koneksi dianggap mati.

JSPing-pong manual di client browser
ws.onopen = () => {
  heartbeat();
};
 
function heartbeat() {
  clearTimeout(ws.pingTimeout);
  ws.pingTimeout = setTimeout(() => {
    console.log("tidak ada pong, menutup koneksi");
    ws.close();
  }, 30000);
}
 
ws.onpong = () => {
  console.log("pong diterima, koneksi sehat");
  heartbeat();
};

Di browser tidak ada API untuk mengirim ping secara manual, jadi contoh di atas memanfaatkan pong otomatis browser sebagai penanda koneksi hidup. Timer 30 detik dimulai ulang setiap kali pong diterima.

Heartbeat di Server ws

Di sisi server Node.js dengan library ws, ping bisa dikirim langsung.

JSHeartbeat di server ws
const wss = new WebSocketServer({ port: 8080 });
 
function heartbeat() {
  clearTimeout(this.isAlive);
  this.isAlive = setTimeout(() => this.terminate(), 30000);
}
 
wss.on("connection", (ws) => {
  ws.isAlive = null;
  heartbeat.call(ws);
  ws.on("pong", () => heartbeat.call(ws));
});
 
setInterval(() => {
  wss.clients.forEach((ws) => {
    if (!ws.isAlive) return;
    ws.ping();
  });
}, 10000);

Setiap 10 detik server mengirim ws.ping() ke semua klien. Jika tidak ada pong dalam 30 detik, ws.terminate() memutus koneksi yang dianggap mati. Pola isAlive yang direset oleh pong ini adalah standar di dokumentasi ws.

Presence Detection

Status Pengguna

Presence adalah informasi di atas level koneksi: bukan hanya koneksi hidup, tapi apa yang sedang dilakukan pengguna.

JSMelacak status presence
const pengguna = new Map();
 
io.on("connection", (socket) => {
  socket.on("presence:set", (status) => {
    pengguna.set(socket.userId, {
      status,
      terakhirAktif: Date.now(),
    });
    io.emit("presence:update", {
      userId: socket.userId,
      status,
    });
  });
 
  socket.on("disconnect", () => {
    pengguna.set(socket.userId, {
      status: "offline",
      terakhirAktif: Date.now(),
    });
  });
});

Map pengguna menyimpan status per pengguna. Saat koneksi putus, status diubah menjadi offline otomatis. Field terakhirAktif bisa menampilkan teks seperti "aktif 5 menit lalu".

Deteksi Idle

Presence tidak hanya soal koneksi — kalian juga bisa melacak aktivitas klien.

JSSet status away saat idle
let idleTimer;
 
socket.on("input:activity", () => {
  clearTimeout(idleTimer);
  setStatus("online");
  idleTimer = setTimeout(() => setStatus("away"), 120000);
});

Timer 120 detik di-reset setiap kali pengguna beraktivitas. Jika tidak ada aktivitas, status berubah menjadi away. Kombinasi koneksi hidup dan aktivitas menghasilkan presence yang jauh lebih akurat.

Presence Broadcasting

Menyebarkan Perubahan Status

Perubahan presence harus disiarkan agar semua klien menampilkan status terbaru.

JSBroadcast perubahan status
function setStatus(status) {
  socket.emit("presence:me", { status });
  socket.to("room:utama").emit("presence:user", {
    userId: socket.userId,
    status,
  });
}

socket.to("room:utama") memastikan hanya anggota room yang menerima pembaruan. Saat masuk aplikasi, klien juga meminta daftar status semua pengguna untuk merender status awal.

Skalabilitas Presence

Pada satu server, Map sederhana sudah cukup. Saat server bertambah banyak, presence harus disimpan di tempat bersama seperti Redis agar setiap instance melihat status yang sama. Pendekatan ini akan dibahas lebih dalam di episode 16.

Konfigurasi Heartbeat Socket.IO

Socket.IO sudah menangani ping-pong secara internal dengan dua opsi utama.

JSKonfigurasi ping di Socket.IO
const io = new Server(server, {
  pingInterval: 25000,
  pingTimeout: 20000,
});

pingInterval menentukan jarak server mengirim ping, dan pingTimeout batas waktu menunggu pong sebelum koneksi diputus. Total di atas berarti koneksi mati terdeteksi dalam maksimal 45 detik. Nilai ini bisa disesuaikan dengan kondisi jaringan pengguna.

Penutup

Episode 11 memberi kalian kemampuan mendeteksi koneksi yang sebenarnya sudah mati dan menampilkan presence yang akurat. Heartbeat mencegah kebocoran resource, presence membuat aplikasi terasa hidup dan responsif.

Inti yang harus dibawa pulang:

  • Ping-pong frame memastikan koneksi yang tampak sehat benar-benar hidup.
  • Setelah timeout tanpa pong, koneksi harus ditutup atau di-terminate.
  • Presence melacak status pengguna di atas level koneksi.
  • Status bisa berupa online, offline, away, dan terakhir aktif.
  • Perubahan presence disiarkan hanya ke room yang relevan.
  • Socket.IO menyediakan pingInterval dan pingTimeout secara bawaan.

Di episode 12 berikutnya kita membahas error handling & reconnection strategies: jenis-jenis kegagalan koneksi, exponential backoff, konfigurasi reconnection Socket.IO, serta pemulihan state setelah koneksi kembali.

Belajar WebSocket - Presence & Heartbeat Mechanisms | Belajar WebSocket