Pola Desain API Gateway: Implementasi Algoritma Token Bucket dan Leaky Bucket dengan Redis

Melindungi API backend dari scraping agresif dan serangan DoS: evaluasi algoritma rate limiting, mitigasi race condition menggunakan skrip atomik Redis Lua, dan header standar RFC 6585.

PuluhLabs Engineering Team, Lead API Platform Engineer · 9 November 2026 · 7 min baca

Pola Desain API Gateway: Implementasi Algoritma Token Bucket dan Leaky Bucket dengan Redis
Pengembangan Web
DECOUPLED

Isi artikel ini

  • Membandingkan Kelemahan Fixed Window vs Keunggulan Token Bucket
  • Mengatasi Race Condition dengan Skrip Redis Lua Atomik
  • Integrasi Middleware API Gateway pada Node.js / Express
  • Menentukan Identitas dan Tingkatan Kuota (Tiered Limits)

Setiap antarmuka pemrograman aplikasi (Application Programming Interface / API) publik maupun gateway internal korporat pasti berhadapan dengan risiko penyalahgunaan lalu lintas trafik. Risiko ini mencakup serangan penolakan layanan (Denial of Service / DoS), bot scraping data harga dan inventaris yang agresif, percobaan peretasan kata sandi secara berulang (brute-force), hingga skrip integrasi pihak ketiga yang mengalami infinite loop.

Tanpa lapisan kontrol lalu lintas yang ketat pada level API Gateway, lonjakan volume request yang tak terkendali akan menguras thread pemrosesan CPU, membanjiri connection pool database, dan melumpuhkan ketersediaan layanan bagi pengguna sah lainnya.

Mekanisme pertahanan paling fundamental untuk menjaga keandalan infrastruktur backend adalah penerapan Rate Limiting. Namun, merancang sistem pembatasan laju trafik terdistribusi yang mampu memproses ratusan ribu request per detik tanpa menimbulkan overhead latensi memerlukan pemahaman mendalam tentang algoritma dan eksekusi atomik pada Redis.

text
Arsitektur Rate Limiting Terdistribusi Berbasis Token Bucket & Redis:
Klien (Browser / Mobile / B2B)
       │
       ▼ [Request Masuk: GET /api/v1/orders]
┌──────────────────────────────────────────────┐
│  API Gateway (Kong / Traefik / Node.js)      │
│  1. Ekstrak Identitas (API Key / Client IP)  │
│  2. Kirim Perintah Atomik ke Redis via Lua   │
└──────┬───────────────────────────────────────┘
       │
       ▼ [EVAL sha_token_bucket.lua key limit capacity refill_rate]
┌──────────────────────────────────────────────┐
│  Redis In-Memory Data Store                  │
│  - Kapasitas Ember (Bucket Capacity): 100    │
│  - Laju Pengisian (Refill Rate): 10 token/dtk│
│  - Token Tersedia: 84                        │
└──────┬───────────────────────────────────────┘
       │
       ├── Jika Token > 0: Kurangi 1 token ──> [Teruskan Request ke Service Backend]
       │
       └── Jika Token = 0: TOLAK SEGERA ────> [HTTP 429 Too Many Requests]
                                                Header: Retry-After: 5

Membandingkan Kelemahan Fixed Window vs Keunggulan Token Bucket #

Terdapat beberapa pendekatan algoritma yang umum digunakan dalam pembatasan laju trafik:

1. Fixed Window Counter (Penghitung Jendela Tetap) #

Pendekatan ini membagi waktu ke dalam blok statis, misalnya 100 request per menit (00.00 - 00.59).

  • Kelemahan Fatal: Rentan terhadap fenomena traffic spike di batas jendela. Jika seorang pengguna mengirimkan 100 request pada detik 00.59 dan 100 request lagi pada detik 01.01, server menerima 200 request hanya dalam kurun waktu 2 detik! Hal ini dapat menumbangkan database seketika.

2. Sliding Window Log (Log Jendela Geser) #

Mencatat timestamp setiap request yang masuk ke dalam sorted set Redis.

  • Kelemahan Fatal: Memakan kapasitas memori RAM yang sangat besar jika trafik mencapai jutaan request, karena setiap entri request harus disimpan secara individual.

3. Token Bucket (Ember Token) #

Algoritma ini dianalogikan seperti sebuah ember penampung token dengan kapasitas maksimum tertentu ($C$). Token ditambahkan ke dalam ember secara kontinu dengan laju tetap ($r$ token per detik).

  • Setiap kali request masuk, request tersebut harus mengambil satu token dari ember.
  • Jika token tersedia di ember, token diambil dan request diteruskan ke backend.
  • Jika ember kosong, request langsung ditolak dengan status HTTP 429 Too Many Requests.
  • Keunggulan: Mampu mengakomodasi lonjakan trafik mendadak (burst traffic) selama isi token di dalam ember masih mencukupi, sambil tetap menjamin laju konsumsi rata-rata jangka panjang tidak melampaui batas yang ditentukan.

Mengatasi Race Condition dengan Skrip Redis Lua Atomik #

Pada arsitektur cloud modern di mana API Gateway berjalan sebagai kluster multi-kontainer, implementasi rate limiting tidak boleh dilakukan dengan membaca nilai token (GET) lalu memperbaruinya (SET) secara terpisah. Di antara jeda dua operasi jaringan tersebut, ratusan kontainer lain dapat membaca nilai yang sama secara bersamaan (race condition), mengakibatkan jumlah request yang lolos melebihi batas kuota.

Solusi wajib untuk masalah ini adalah mengeksekusi seluruh logika pengecekan dan pengurangan token di dalam satu Skrip Redis Lua yang dijamin dieksekusi secara atomik di dalam single-thread engine Redis.

Berikut adalah implementasi skrip Lua Token Bucket berperforma tinggi:

lua
-- token_bucket.lua
local key = KEYS[1]
local capacity = tonumber(ARGV[1])    -- Kapasitas maksimum ember (burst limit)
local refill_rate = tonumber(ARGV[2]) -- Jumlah token bertambah per detik
local requested = tonumber(ARGV[3])   -- Jumlah token yang diminta (biasanya 1)
local now = tonumber(ARGV[4])         -- Waktu saat ini (epoch timestamp detik)

-- Ambil data state ember sebelumnya
local data = redis.call('HMGET', key, 'tokens', 'last_updated')
local tokens = tonumber(data[1])
local last_updated = tonumber(data[2])

if tokens == nil then
  -- Inisialisasi awal saat key pertama kali dibuat
  tokens = capacity
  last_updated = now
else
  -- Hitung pertambahan token berdasarkan selisih waktu yang berlalu
  local elapsed = math.max(0, now - last_updated)
  tokens = math.min(capacity, tokens + (elapsed * refill_rate))
  last_updated = now
end

if tokens >= requested then
  -- Token mencukupi: izinkan request dan kurangi token
  tokens = tokens - requested
  redis.call('HMSET', key, 'tokens', tokens, 'last_updated', last_updated)
  -- Set TTL otomatis agar Redis membersihkan kunci yang sudah tidak aktif
  redis.call('EXPIRE', key, math.ceil(capacity / refill_rate) * 2)
  return { 1, math.floor(tokens) } -- 1 = ALLOWED, tokens tersisa
else
  -- Token habis: tolak request
  redis.call('HMSET', key, 'tokens', tokens, 'last_updated', last_updated)
  return { 0, math.floor(tokens) } -- 0 = BLOCKED
end

Integrasi Middleware API Gateway pada Node.js / Express #

Middleware mengeksekusi skrip Lua di atas dan menyematkan header HTTP standar industri ke browser klien:

typescript
// middleware/rateLimiter.ts
import { Request, Response, NextFunction } from 'express';
import Redis from 'ioredis';
import fs from 'fs';
import path from 'path';

const redis = new Redis(process.env.REDIS_URL || 'redis://127.0.0.1:6379');
const luaScript = fs.readFileSync(path.join(__dirname, 'token_bucket.lua'), 'utf8');

// Muat skrip ke Redis SHA script cache untuk eksekusi ultra cepat
let scriptSha: string;
redis.script('load', luaScript).then((sha) => {
  scriptSha = sha as string;
});

export async function tokenBucketRateLimiter(
  req: Request,
  res: Response,
  next: NextFunction
) {
  // 1. Identifikasi klien: Utamakan API Key, fallback ke IP asli Cloudflare
  const clientId = (req.headers['x-api-key'] as string) ||
                   (req.headers['cf-connecting-ip'] as string) ||
                   req.ip;

  const key = `ratelimit:client:${clientId}`;
  const capacity = 100;     // Maksimum burst 100 request
  const refillRate = 10;    // Isi ulang 10 token per detik
  const requested = 1;
  const now = Math.floor(Date.now() / 1000);

  try {
    const result = await redis.evalsha(
      scriptSha,
      1,
      key,
      capacity,
      refillRate,
      requested,
      now
    ) as [number, number];

    const isAllowed = result[0] === 1;
    const remainingTokens = result[1];

    // 2. Sematkan Header Standar IETF RFC 6585
    res.setHeader('X-RateLimit-Limit', capacity);
    res.setHeader('X-RateLimit-Remaining', remainingTokens);

    if (!isAllowed) {
      const retryAfterSeconds = Math.ceil((1 - remainingTokens) / refillRate);
      res.setHeader('Retry-After', Math.max(1, retryAfterSeconds));
      return res.status(429).json({
        error: 'Too Many Requests',
        message: 'Batas kuota akses API terlampaui. Silakan perlambat frekuensi permintaan Anda.',
        retry_after_seconds: Math.max(1, retryAfterSeconds),
      });
    }

    next();
  } catch (error) {
    // Fail-open strategy: Jika Redis down, jangan sampai sistem menolak pengguna sah
    console.error('[RateLimiter Error]', error);
    next();
  }
}

Menentukan Identitas dan Tingkatan Kuota (Tiered Limits) #

Penerapan rate limiting yang efektif harus membedakan batas limit berdasarkan segmen pengguna:

  1. Endpoint Autentikasi Publik (/api/auth/login): Terapkan limit ketat berbasis IP (misalnya maksimal 5 request per menit) untuk melumpuhkan serangan credential stuffing.
  2. Klien Publik Tanpa Autentikasi: Batasi berdasarkan IP geografis dengan kuota 60 request per menit.
  3. Klien Enterprise B2B: Batasi berdasarkan API Key unik dengan kuota hingga 5.000 request per menit, dilengkapi dashboard analitik penggunaan kuota secara transparan.

Dengan menerapkan algoritma Token Bucket yang dieksekusi secara atomik menggunakan Redis Lua, infrastruktur API perusahaan memiliki perlindungan tangguh dari lonjakan anomali trafik tanpa mengorbankan kecepatan latensi respons backend.

Bagikan Artikel Ini:
Topik Terkait:API GatewayRate LimitingRedisLua ScriptingMicroservices
Istilah Teknis Terkait (Knowledge Graph Glossary)
Jejaring Entitas & Solusi Teknis Terkait
3 Solusi Terintegrasi
Architecture Matrix

Perbandingan Headless CMS vs Monolitik

Kajian komparatif performa, keamanan OWASP, dan total biaya kepemilikan (TCO).

Buka Solusi
Planning Tool

Kalkulator Investasi & Jadwal Website

Estimasi biaya pembuatan website company profile, portal B2B, atau web app kustom.

Buka Solusi
Partnership Hub

Kemitraan White-Label untuk Agensi

Dukungan rekayasa teknis rahasia di balik layar agensi Anda dengan NDA resmi.

Buka Solusi
TO
PuluhLabs Engineering TeamPenulis Terverifikasi

Lead API Platform Engineer

Praktisi dan konsultan pengembangan platform digital terpercaya dengan pengalaman memimpin perancangan lebih dari 50+ proyek untuk skala korporat, bisnis B2B, dan instansi profesional. Berfokus pada pembangunan solusi web yang tangguh, cepat, aman, serta dirancang untuk mendorong pertumbuhan bisnis jangka panjang.

Ditinjau & divalidasi oleh: Tim Profesional PuluhLabs
Terakhir ditinjau: 9 November 2026

Ingin Menerapkan Standar Performa Ini pada Proyek Agensi Anda?

Tim PuluhLabs siap menjadi mitra rekayasa digital rahasia (white-label) untuk agensi Anda. Garansi performa skor Lighthouse 90+, Core Web Vitals hijau, dan 100% hak milik kode.

Konsultasi Proyek Bersama Tim PuluhLabs

Artikel Rekomendasi Selanjutnya

Lihat Semua
  1. Pengembangan Web

    Arsitektur Micro-Frontends vs Modular Monolith: Panduan Memilih untuk Aplikasi Web Skala Enterprise

  2. Pengembangan Web

    Implementasi Zero-Trust Architecture pada REST API dan Webhook Korporat

  3. Pengembangan Web

    Optimasi Query PostgreSQL Skala Jutaan Baris: Indexing, Table Partitioning, dan Connection Pooling