Belajar WebSocket - Rate Limiting & Throttling
Episode 13 of 34

Belajar WebSocket - Rate Limiting & Throttling

Episode ini membahas perlindungan server dari penyalahgunaan: algoritma rate limiting seperti token bucket dan sliding window, pembatasan per pengguna dan per koneksi, throttling di sisi klien, serta penanganan backpressure.

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

Pendahuluan

Satu klien nakal yang mengirim seribu pesan per detik bisa melumpuhkan server yang melayani ribuan pengguna normal. Rate limiting adalah pagar yang membatasi seberapa banyak permintaan yang boleh dilakukan dalam satu periode waktu.

Episode 13 membahas rate limiting: membatasi frekuensi aksi, dan throttling: memperlambat pengiriman data. Kalian akan mempelajari algoritma klasik seperti token bucket, implementasi di server Node.js, serta cara klien menghormati batas yang diberikan server.

Mengapa Rate Limiting

Bahaya Tanpa Pembatasan

Tanpa rate limiting, server rentan terhadap berbagai masalah:

  • Abuse: script otomatis membanjiri server dengan pesan spam.
  • Resource exhaustion: CPU dan memori habis untuk memproses pesan murahan.
  • DDoS: koneksi massal memenuhi kapasitas server.
  • Cost explosion: biaya bandwidth dan komputasi membengkak tanpa kontrol.

Algoritma Rate Limiting

Token Bucket

JSImplementasi token bucket sederhana
const state = new Map();
 
function izinkan(userId, kapasitas = 10, perDetik = 1) {
  const sekarang = Date.now() / 1000;
  const s = state.get(userId) || { token: kapasitas, waktu: sekarang };
 
  s.token = Math.min(
    kapasitas,
    s.token + (sekarang - s.waktu) * perDetik
  );
  s.waktu = sekarang;
 
  if (s.token < 1) {
    return false;
  }
  s.token -= 1;
  state.set(userId, s);
  return true;
}

izinkan(userId) mengembalikan true jika token tersisa, false jika klien dibatasi. Token bertambah seiring waktu dengan laju perDetik dan dibatasi maksimal kapasitas.

Sliding Window

Alternatif yang umum dipakai adalah window yang bergeser berdasarkan waktu.

Pasang middleware rate limit
bun add express-rate-limit

Library express-rate-limit mengimplementasikan sliding window untuk REST. Untuk WebSocket, kalian mengaplikasikan logika yang sama di handler pesan, bukan di middleware HTTP.

Implementasi di Server

Batas Per Pengguna dan Per Koneksi

Rate limit diterapkan di dua level: per koneksi dan per pengguna terautentikasi.

JSRate limit pada handler pesan
wss.on("connection", (ws) => {
  ws.limit = { jumlah: 0, mulai: Date.now() };
 
  ws.on("message", (data) => {
    const kini = Date.now();
    if (kini - ws.limit.mulai > 10000) {
      ws.limit = { jumlah: 0, mulai: kini };
    }
 
    ws.limit.jumlah += 1;
    if (ws.limit.jumlah > 30) {
      ws.close(1008, "terlalu banyak pesan");
      return;
    }
    prosesPesan(data);
  });
});

Window 10 detik dengan maksimal 30 pesan per koneksi di atas. Setelah lewat batas, ws.close(1008, "terlalu banyak pesan") memutus koneksi dengan alasan policy violation.

Redis untuk Banyak Server

Saat server lebih dari satu, Map di memori tidak lagi cukup karena setiap instance punya hitungan sendiri. Simpan counter di Redis dengan TTL.

JSCounter rate limit di Redis
const redis = require("redis");
const client = redis.createClient();
 
async function batasi(userId) {
  const kunci = "rl:" + userId;
  const jumlah = await client.incr(kunci);
  if (jumlah === 1) {
    await client.expire(kunci, 10);
  }
  return jumlah > 30;
}

client.incr(kunci) menaikkan counter atomik, dan client.expire(kunci, 10) membersihkannya setelah 10 detik. Semua instance server membaca counter yang sama, sehingga pembatasan konsisten lintas instance.

Throttling di Sisi Klien

Debounce dan Batching

Server bukan satu-satunya tempat untuk memperlambat. Klien yang baik menahan input pengguna yang berlebihan.

JSDebounce input pengguna
let timer;
 
input.oninput = () => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    ws.send(JSON.stringify({ type: "ketik", teks: input.value }));
  }, 300);
};

clearTimeout(timer) membatalkan pengiriman sebelumnya, sehingga hanya pesan terakhir dalam 300 ms yang dikirim. Debounce sangat berguna untuk fitur seperti status mengetik dan pencarian live.

Queue dengan Batas

Saat offline, pesan yang dikirim harus diantrekan, tapi antrean tidak boleh tumbuh tanpa batas.

JSQueue dengan batas maksimal
const antrean = [];
 
function kirim(pesan) {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify(pesan));
  } else {
    if (antrean.length >= 50) {
      antrean.shift();
    }
    antrean.push(pesan);
  }
}

antrean.shift() membuang pesan paling tua saat antrean melebihi 50 item. Ini mencegah memori klien membengkak saat koneksi lama mati.

Backpressure Handling

Server yang menerima data lebih cepat daripada memprosesnya membutuhkan backpressure. Library ws menyediakan bufferedAmount untuk mendeteksinya.

JSDeteksi bufferedAmount
function kirimAman(ws, pesan) {
  if (ws.bufferedAmount > 1024 * 1024) {
    console.warn("antrean keluar penuh, menunda pengiriman");
    return false;
  }
  ws.send(JSON.stringify(pesan));
  return true;
}

ws.bufferedAmount menunjukkan berapa byte yang belum terkirim. Jika melebihi ambang, kalian bisa menjatuhkan pesan non-kritis, memberi tahu klien, atau mengurangi laju produksi data.

Penutup

Episode 13 memberi kalian perlindungan berlapis: server membatasi dengan algoritma yang adil, penyimpanan counter yang bekerja lintas instance, dan klien yang menahan diri dengan debounce dan antrean berbatas.

Inti yang harus dibawa pulang:

  • Rate limiting mencegah abuse, resource exhaustion, dan DDoS.
  • Token bucket memungkinkan lonjakan kecil dengan rata-rata yang stabil.
  • Batasi per koneksi dan per pengguna terautentikasi.
  • Redis membuat counter konsisten di banyak instance server.
  • Debounce dan antrean berbatas menghormati server dari sisi klien.
  • bufferedAmount mendeteksi backpressure sebelum memori penuh.

Di episode 14 berikutnya kita membahas message queuing & reliability: jaminan pengiriman, acknowledgement, antrean pesan, dan strategi menjaga urutan serta mencegah kehilangan data.

Belajar WebSocket - Rate Limiting & Throttling | Belajar WebSocket