Baru aja kalian merilis fitur login atau endpoint pencarian produk. Awalnya semua berjalan adem ayem. Eh, tiba-tiba di suatu malam ada bot nakal yang nyoba nembak ribuan password lewat brute-force, atau ada pengguna iseng yang nge-refresh aplikasi seratus kali dalam semenit.
Seketika itu juga CPU server kalian melonjak 100%, koneksi database habis terkuras, dan pengguna lain yang cuma mau transaksi malah dapat pesan Server Timeout. Gimana nggak pusing, coba?
Masalah ini udah jadi mimpi buruk klasik buat pengembang backend. Kabar baiknya, ada satu tameng paling ampuh buat nangkalnya: Rate Limiting.
Poin Penting
- Rate Limiting ngebatesin berapa kali satu klien boleh manggil API dalam kurun waktu tertentu.
- Token Bucket fleksibel dan kuat nangani lonjakan trafik singkat, Leaky Bucket ngeluarin request dengan laju konstan, sedangkan Sliding Window paling akurat nyegah serangan di batas pergantian menit.
- Redis jadi pasangan ideal karena operasi atomiknya sanggup ngecek kuota dalam hitungan sub-milidetik tanpa membebani database utama.
- Endpoint autentikasi dan endpoint ber-resource berat adalah prioritas pertama yang wajib dipasangi limiter.
Apa Sih Sebenarnya Rate Limiting Itu?
Secara sederhana, Rate Limiting itu mekanisme buat ngebatesin seberapa sering seorang klien—entah dilihat dari IP address, API Key, atau User ID—boleh manggil endpoint API kalian dalam kurun waktu tertentu.
Kalau klien ngirim request melebihi batas yang udah ditentukan, misalnya maksimal 60 request per menit, server bakal nolak request itu dan ngembaliin status code standar HTTP 429 Too Many Requests.
Biar kebayang, anggap aja API kalian itu wahana roller coaster yang cuma muat 20 orang sekali jalan. Kalau ada 500 orang langsung nyerbu pintu masuk barengan tanpa ada satpam yang ngatur antrean, pintunya bakal roboh dan wahananya malah nggak bisa jalan sama sekali. Nah, satpam itulah rate limiter-nya. Pengunjung cuma boleh masuk bergiliran sesuai kuota per menit, sisanya disuruh nunggu sejenak.
Tiga Algoritma Rate Limiting yang Populer
Ada beberapa strategi yang biasa dipakai di balik layar, dan masing-masing punya karakter yang beda.
1. Token Bucket
Algoritma Token Bucket ini bekerja kayak ember yang terus diisi token secara berkala dengan laju konstan, misalnya 1 token tiap detik. Setiap request yang masuk harus ngambil 1 token. Kalau embernya kosong, request langsung ditolak sampai token barunya terisi lagi.
Kelebihannya, algoritma ini fleksibel banget dan sanggup nampung lonjakan trafik singkat (burst), lho.
2. Leaky Bucket
Kebalikannya, yang ini kayak ember bocor di bawahnya. Request yang masuk ditampung dulu di dalam ember, terus diproses satu per satu dengan kecepatan konstan lewat lubang di bawahnya. Kalau request datang terlalu deras sampai embernya kepenuhan, maka kelebihannya bakal tumpah alias dibuang.
3. Sliding Window Log / Counter
Yang ini ngitung jumlah request dalam jendela waktu bergulir, misalnya 60 detik terakhir dihitung dari waktu sekarang. Akurasinya bagus banget buat nyegah serangan yang sengaja nunggu di batas pergantian menit (boundary reset attack).
Kenapa Redis Jadi Pasangan Ideal buat Rate Limiter?
Nyimpen hitungan request di database relasional kayak PostgreSQL itu justru bikin database kalian makin terbebani, tuh. Bayangin, cuma buat ngecek satu angka kuota, database harus baca-tulis jutaan baris. Boros banget, kan? 😅
Di sinilah Redis berperan. Karena jalan langsung di dalam memori (RAM) dan mendukung operasi atomik kayak INCR dan EXPIRE, Redis sanggup ngecek kuota request dalam hitungan sub-milidetik tanpa ngeganggu database utama.
Contoh Implementasi Sederhana di FastAPI
Berikut contoh rate limiter berbasis Redis di Python pakai FastAPI:
import redis.asyncio as redis
from fastapi import FastAPI, HTTPException, Request, status
app = FastAPI()
r = redis.from_url("redis://localhost:6379", encoding="utf-8", decode_responses=True)
RATE_LIMIT = 5 # Maksimal 5 request
WINDOW_SECONDS = 60 # Per 60 detik
@app.middleware("http")
async def rate_limit_middleware(request: Request, call_next):
client_ip = request.client.host
key = f"rate_limit:{client_ip}"
# INCR bersifat atomik, jadi aman dipanggil dari banyak worker sekaligus
current = await r.incr(key)
# Pasang TTL cuma di request pertama. Kalau dipasang di setiap request,
# jendela waktunya bakal terus ter-reset dan limitnya nggak pernah habis.
if current == 1:
await r.expire(key, WINDOW_SECONDS)
if current > RATE_LIMIT:
retry_after = await r.ttl(key)
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Terlalu banyak request! Silakan coba lagi sebentar ya.",
headers={"Retry-After": str(max(retry_after, 0))},
)
return await call_next(request)
@app.get("/api/data-publik")
async def get_data():
return {"message": "Ini data aman yang terlindungi oleh Rate Limiter!"}
Nah, perhatikan urutan INCR lalu EXPIRE di atas ya. Ini contoh fixed window yang paling gampang, dan atomik karena kita cuma baca hasil balikan INCR. Kalau kalian ambil nilai dulu pakai GET, baru ngecek di kode, terus nge-INCR—itu udah bukan operasi atomik lagi, dan dua request bersamaan bisa lolos melewati batasnya.
Kapan Rate Limiting Wajib, Kapan Sebaiknya Nggak?
Rate limiting itu murah dan gampang dipasang, sih. Tapi bukan berarti semua endpoint harus dikasih batas yang ketat.
- Wajib dipasang di endpoint autentikasi kayak
/login,/register, dan/forgot-password—itu pintu favorit brute-force—serta endpoint pencarian atau ekspor yang makan resource berat. - Kasih kelonggaran di endpoint publik yang cuma baca data ringan, kayak halaman artikel atau feed. Batas yang terlalu ketat di sini malah bikin pengguna asli kena blokir, terutama kalau mereka di belakang satu NAT kantor atau kampus.
- Kirim header informatif. Sertakan
Retry-After,X-RateLimit-Limit, danX-RateLimit-Remainingsupaya aplikasi frontend tahu kapan boleh nyoba lagi tanpa nebak-nebak.
Kalau skalanya udah enterprise, rate limiting di level aplikasi bisa kalian padukan dengan proteksi di level DNS/CDN kayak Cloudflare atau AWS WAF.
Membangun API yang cepat itu menyenangkan, tapi memastikan API-nya tetap berdiri saat diserbu ribuan request liar itu jauh lebih krusial. Memasang rate limiting sejak awal itu langkah murah yang nyelametin server kalian dari downtime yang sebenernya nggak perlu.
Selamat ber-rate limiting ria, dan semoga server kalian tidur tenang malam ini! 👋