Rate Limiting API: 4 Algoritma dan Cara Pakainya di Express

Bayangkan API buatanmu mulai ramai dipakai. Suatu malam, server tiba-tiba lambat. Setelah dicek, ada satu alamat IP yang mengirim ribuan request per menit ke endpoint login. Tidak ada yang rusak di kodenya, tetapi server kewalahan dan pengguna lain ikut terkena dampaknya.

Masalah seperti ini diselesaikan dengan rate limiting API, yaitu teknik membatasi jumlah request yang boleh dikirim seorang klien dalam jangka waktu tertentu. Di artikel ini kamu akan belajar cara kerjanya, empat algoritma yang umum dipakai, dan cara memasangnya di Express.js langkah demi langkah.

Apa Itu Rate Limiting API?

Rate limiting API adalah mekanisme yang membatasi seberapa sering klien boleh memanggil API. Contoh aturannya: “maksimal 100 request per 15 menit untuk setiap IP”. Kalau jatahnya habis, server menolak request berikutnya sampai periode berganti.

Analogi sederhananya adalah antrean di loket. Petugas hanya bisa melayani sejumlah orang per jam. Tanpa batas, satu orang yang membawa seratus berkas bisa menahan semua orang di belakangnya.

Server yang menolak request akan membalas dengan status HTTP 429 Too Many Requests. Kode ini dibuat khusus untuk kasus “kamu terlalu sering meminta”.

Kenapa API Perlu Dibatasi?

Ada empat alasan utama untuk memasang rate limiting API sejak awal.

  1. Mencegah brute force. Penyerang bisa mencoba ribuan kombinasi password di endpoint login. Dengan pembatasan, serangan jadi sangat lambat.
  2. Melindungi server dari lonjakan trafik. Bug di aplikasi klien, misalnya loop yang memanggil API tanpa henti, bisa membuat server tumbang tanpa niat jahat.
  3. Menjaga keadilan antar pengguna. Satu pengguna rakus tidak boleh menghabiskan sumber daya yang dipakai semua orang.
  4. Mengontrol biaya. Kalau API-mu memanggil layanan berbayar seperti database besar atau layanan AI, setiap request punya harga.

Rate limiting juga melengkapi pengaman lain. Jika kamu sudah memahami cara kerja autentikasi lewat JWT vs session, anggap rate limiting sebagai lapisan tambahan yang menjaga pintu tetap aman walaupun kuncinya benar.

4 Algoritma Rate Limiting yang Perlu Kamu Tahu

Aturan “100 request per 15 menit” bisa diterapkan dengan beberapa cara. Masing-masing punya kelebihan dan kekurangan.

1. Fixed Window

Waktu dibagi menjadi jendela tetap, misalnya setiap 1 menit. Server menghitung request dalam jendela itu dan mereset hitungan saat jendela baru dimulai.

  • Kelebihan: paling mudah dibuat dan hemat memori.
  • Kekurangan: rawan lonjakan di batas jendela. Klien bisa mengirim 100 request pada detik ke-59, lalu 100 lagi pada detik ke-61. Artinya 200 request dalam dua detik, padahal batasnya 100 per menit.

2. Sliding Window

Jendela waktunya bergeser mengikuti waktu sekarang. Setiap request dihitung berdasarkan 60 detik terakhir, bukan menurut menit di jam dinding.

  • Kelebihan: menutup celah lonjakan di batas jendela.
  • Kekurangan: butuh lebih banyak memori karena harus mencatat waktu tiap request.

3. Token Bucket

Bayangkan ember berisi token. Setiap request mengambil satu token, dan token terisi ulang dengan kecepatan tetap. Kalau ember kosong, request ditolak.

  • Kelebihan: mengizinkan lonjakan singkat (burst) selama token masih ada, tetapi tetap menjaga rata-rata laju.
  • Kekurangan: logikanya sedikit lebih rumit.

Berikut contoh sederhana dalam JavaScript:

javascript

class TokenBucket {
  constructor(capacity, refillPerSecond) {
    this.capacity = capacity;
    this.tokens = capacity;
    this.refillPerSecond = refillPerSecond;
    this.lastRefill = Date.now();
  }

  allow() {
    const now = Date.now();
    const elapsed = (now - this.lastRefill) / 1000;
    this.tokens = Math.min(
      this.capacity,
      this.tokens + elapsed * this.refillPerSecond
    );
    this.lastRefill = now;

    if (this.tokens >= 1) {
      this.tokens -= 1;
      return true;
    }
    return false;
  }
}

const bucket = new TokenBucket(10, 2); // kapasitas 10, isi ulang 2 token/detik
console.log(bucket.allow()); // true

4. Leaky Bucket

Request masuk ke ember yang “bocor” dengan kecepatan tetap. Request keluar dari ember dalam laju yang stabil, dan kalau ember penuh, request baru dibuang.

  • Kelebihan: menghasilkan aliran request yang sangat rata ke server.
  • Kekurangan: tidak fleksibel untuk lonjakan singkat yang sebenarnya wajar.

Perbandingan Singkat

AlgoritmaKemudahanMenangani burstCocok untuk
Fixed WindowSangat mudahKurang baikProyek kecil dan prototipe
Sliding WindowSedangBaikAPI publik
Token BucketSedangSangat baikAPI dengan trafik tidak merata
Leaky BucketSedangTidak adaLayanan yang butuh laju stabil

Untuk pemula, fixed window sudah cukup. Pindah ke sliding window atau token bucket kalau trafikmu mulai besar.

Cara Memasang Rate Limiting API di Express.js

Cara paling cepat adalah memakai paket express-rate-limit.

Langkah 1: Install Paket

bash

npm install express express-rate-limit

Langkah 2: Buat Limiter Global

javascript

const express = require('express');
const { rateLimit } = require('express-rate-limit');

const app = express();

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 menit
  limit: 100,               // maksimal 100 request per IP
  standardHeaders: 'draft-7',
  legacyHeaders: false,
  message: {
    status: 429,
    error: 'Terlalu banyak request. Coba lagi beberapa menit lagi.'
  }
});

app.use(limiter);

app.get('/api/produk', (req, res) => {
  res.json({ data: ['Kopi', 'Teh', 'Susu'] });
});

app.listen(3000);

Opsi standardHeaders membuat server menyertakan header yang memberi tahu klien sisa jatahnya, sehingga aplikasi klien bisa menyesuaikan diri.

Langkah 3: Batasi Endpoint Sensitif Lebih Ketat

Tidak semua endpoint sama pentingnya. Login dan registrasi sebaiknya dibatasi lebih ketat daripada endpoint baca data.

javascript

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  limit: 5, // hanya 5 percobaan login per 15 menit
  message: { error: 'Terlalu banyak percobaan login.' }
});

app.post('/api/login', loginLimiter, (req, res) => {
  // logika login
});

Langkah 4: Tangani Respons 429 di Sisi Klien

Klien yang baik menghormati batas. Kalau menerima status 429, tunggu dulu sebelum mencoba lagi.

javascript

async function ambilData() {
  const res = await fetch('/api/produk');

  if (res.status === 429) {
    const tunggu = res.headers.get('Retry-After') || 60;
    console.log(`Kena limit. Coba lagi dalam ${tunggu} detik.`);
    return null;
  }
  return res.json();
}

Kalau permintaan dari frontend ke API-mu malah gagal dengan pesan aneh di console, periksa juga apakah itu masalah CORS. Panduannya ada di artikel CORS error dan cara memperbaikinya.

Rate Limiting di Banyak Server: Pakai Redis

Ada jebakan yang sering terlewat. Secara bawaan, express-rate-limit menyimpan hitungan di memori proses. Kalau aplikasimu berjalan di beberapa server atau container, setiap server punya hitungan sendiri. Klien yang dibatasi 100 request bisa menembus 300 request kalau ada tiga server.

Solusinya adalah menyimpan hitungan di penyimpanan bersama seperti Redis. Semua server membaca dan menulis ke tempat yang sama, sehingga batasnya konsisten. Paket seperti rate-limit-redis menyediakan store siap pakai untuk express-rate-limit.

Kesalahan Umum Saat Memasang Rate Limiting

  • Membatasi berdasarkan IP saja. Banyak pengguna di satu kantor atau kampus berbagi satu IP publik. Untuk API yang butuh login, batasi berdasarkan ID pengguna atau API key.
  • Lupa setelan proxy. Kalau aplikasi berada di belakang Nginx atau load balancer, semua request terlihat berasal dari satu IP. Atur app.set('trust proxy', 1) agar IP asli terbaca.
  • Batas terlalu ketat. Aplikasi yang sah bisa ikut terblokir. Mulai dari angka longgar, lalu pantau trafik dan sesuaikan.
  • Tidak memberi tahu klien. Sertakan header sisa kuota dan pesan error yang jelas supaya pengembang lain tidak bingung.
  • Mengira ini cukup sebagai pengaman. Rate limiting hanya satu lapisan. Tetap gunakan validasi input dan autentikasi yang benar.

Rate Limiting vs Idempotency: Apa Bedanya?

Keduanya sering disebut berdampingan, tetapi tugasnya berbeda. Rate limiting membatasi seberapa sering klien boleh meminta. Idempotency pada REST API memastikan request yang sama tidak diproses dua kali. Dalam API yang matang, keduanya dipakai bersamaan.

Kalau kamu masih menimbang gaya API yang akan dibangun, baca juga perbandingan REST API vs GraphQL. Di GraphQL, rate limiting biasanya dihitung dari kompleksitas query, bukan sekadar jumlah request.

Pertanyaan yang Sering Diajukan (FAQ)

Apa bedanya rate limiting dan throttling?
Rate limiting menolak request yang melebihi batas. Throttling memperlambat atau menunda request supaya tetap berada dalam batas.

Berapa batas request yang ideal?
Tidak ada angka baku. Untuk endpoint umum, 100 request per 15 menit adalah titik awal yang wajar. Untuk login, 5 sampai 10 percobaan per 15 menit lazim dipakai.

Apakah rate limiting menghentikan serangan DDoS?
Tidak sepenuhnya. Serangan DDoS skala besar perlu perlindungan di level jaringan, misalnya lewat CDN atau layanan khusus. Rate limiting di aplikasi membantu untuk trafik berlebih dalam skala lebih kecil.

Apa arti status HTTP 429?
Artinya klien mengirim terlalu banyak request dalam waktu singkat. Dokumentasi MDN tentang status 429 menjelaskannya lengkap, termasuk header Retry-After.

Kesimpulan

Rate limiting API adalah pengaman sederhana dengan dampak besar. Ia melindungi server dari spam, menjaga keadilan antar pengguna, dan menekan risiko brute force. Mulailah dengan fixed window lewat express-rate-limit, beri batas lebih ketat untuk endpoint sensitif, dan pindah ke Redis saat aplikasimu berjalan di banyak server.

Coba pasang limiter pada satu endpoint di proyekmu hari ini, lalu uji dengan mengirim request berulang sampai muncul status 429. Kalau ada pertanyaan, tulis di kolom komentar.

Leave a Reply

Your email address will not be published. Required fields are marked *