Belajar Backend Developer - Rate Limiting & DDoS Protection
Episode 20 of 28

Belajar Backend Developer - Rate Limiting & DDoS Protection

Mempertahankan ketersediaan API dari brute-force dan banjir request: rate limiting per IP dan per akun dengan store Redis, throttling halus, peran WAF dan CDN dalam melawan DDoS, serta lapisan pertahanan berjenjang

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Di episode 17 rate limiting disebut sebagai pertahanan dasar. Sekarang kita bedah penuh: rate limiting dan DDoS protection — dua pertahanan yang menjaga API tetap hidup. Endpoint login tanpa batas bisa dibanjiri jutaan percobaan; API tanpa proteksi banjir bisa roboh saat traffic liar datang — baik dari serangan maupun event yang viral.

Mengapa lapisan ini penting? Karena ini masalah ketersediaan — bukan hanya keamanan data. Server yang down karena DDoS kehilangan uang dan kepercayaan. Episode ini membangun rate limiting yang benar (termasuk store Redis untuk distribusi), throttling halus, dan strategi WAF/CDN melawan DDoS.

Rate Limiting Dasar

Rate limiting membatasi jumlah request dalam satu jendela waktu. Di episode 17 kita pakai express-rate-limit global; sekarang kita bedah strateginya.

Rate limiter global
import { rateLimit } from "express-rate-limit"
 
export const globalLimiter = rateLimit({
  windowMs: 60 * 1000,
  limit: 100,
  standardHeaders: "draft-7",
  legacyHeaders: false,
  message: { error: "TOO_MANY_REQUESTS", message: "Terlalu banyak request" },
})

Batas harus berbeda per jenis route — jangan satu batas untuk semua:

RouteBatasAlasan
Login/register20 per 15 menit per IPAnti brute-force
Checkout/payment10 per menit per akunAnti abuse biaya
Baca katalog100 per menit per IPRamah untuk umum
Webhook internal5.000 per menitPartner sah
Batas ketat khusus login
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  limit: 20,
  standardHeaders: "draft-7",
  legacyHeaders: false,
  message: { error: "TOO_MANY_ATTEMPTS", message: "Terlalu banyak percobaan" },
})
 
router.post("/v1/auth/login", authLimiter, login)

Per IP vs Per Akun

Rate limit per IP bisa diakali — penyerang punya ribuan IP (botnet, proxy). Batas per akun jauh lebih efektif karena akun sulit diganti massal:

Rate limit per akun di Redis
import { Redis } from "ioredis"
 
const redis = new Redis(process.env.REDIS_URL!)
 
async function hitLimit(key: string, max: number, windowSec: number) {
  const count = await redis.incr(key)
  if (count === 1) await redis.expire(key, windowSec)
  return count > max
}
 
router.post("/v1/auth/login", async (req, res) => {
  const email = normalize(req.body.email)
  // batas per akun (ketat) + per IP (longgar) = dua jaring pengaman
  if (await hitLimit(`login:account:${email}`, 5, 900)) {
    return res.status(429).json({ error: "TOO_MANY_ATTEMPTS" })
  }
  if (await hitLimit(`login:ip:${req.ip}`, 20, 900)) {
    return res.status(429).json({ error: "TOO_MANY_ATTEMPTS" })
  }
  // lanjut validasi credential...
})

INCR adalah operasi atomik (episode 6) — aman dari race condition. Kombinasi per akun + per IP adalah pola standar.

Note

Store Redis adalah wajib saat aplikasi diskala (episode 21). Rate limiter di memori proses berarti setiap instance punya hitungan sendiri — dengan 3 instance, batas efektif jadi 3x lipat, dan penyerang tinggal menyebar request. Store bersama di Redis membuat counter global konsisten.

Throttling: Memperlambat, Bukan Menolak

Menolak dengan 429 bisa memukul user sah (NAT kantor berbagi IP). Alternatifnya slow down — memperlambat respons bertahap:

Slow down halus
import { slowDown } from "express-slow-down"
 
export const apiSlowDown = slowDown({
  windowMs: 60 * 1000,
  delayAfter: 30,
  delayMs: (hits) => Math.min((hits - 30) * 100, 1000),
})

Setelah 30 request/menit, tiap request berikutnya ditunda hingga 1 detik. Penyerang otomatis melambat; user manusia tidak merasakan. Strategi gabungan: slowDown untuk seluruh API, rateLimit ketat untuk login dan aksi mahal.

Melawan DDoS: Pertahanan Berjenjang

DDoS (Distributed Denial of Service) membanjiri sistem dengan traffic dari banyak sumber. Rate limit aplikasi tidak cukup — banjir jutaan paket harus dihentikan di lapisan terluar:

100%

Lapisan 1: CDN dan WAF

  • CDN (CloudFront/Cloudflare) menyerap traffic besar di edge — server kita tidak pernah melihat banjir.
  • WAF (Web Application Firewall) memfilter request berbahaya: SQL injection patterns, bot, geo-blocking, dan challenge (CAPTCHA) untuk traffic mencurigakan.
text
WAF rules contoh:
- Tolak request dengan payload injection pattern
- Challenge browser untuk traffic tanpa header browser
- Blokir IP/ASN yang dikenal sebagai sumber serangan

Lapisan 2: Load Balancer

Load balancer membagi traffic dan bisa menerapkan batas kasar per IP. Ia juga memisahkan internet publik dari service internal — database dan worker tidak pernah terekspos.

Lapisan 3: Aplikasi

Di sini rate limit presisi bekerja: per akun, per route, dengan konteks bisnis yang tidak bisa diketahui WAF.

Warning

DDoS tidak bisa dimenangi sendirian — melawan ratusan Gbps traffic tanpa CDN/WAF mustahil. Strategi yang benar: pindahkan pertahanan ke edge (CDN + WAF) sejak awal, dan pastikan lapisan aplikasi sanggup melayani traffic sah maksimal. Menambah server saat DDoS berlangsung hanya menambah target.

Proteksi Endpoint Kritis

Endpoint yang menimbulkan biaya atau efek samping butuh proteksi ekstra:

1. Pembayaran dan Checkout

Batas ketat untuk aksi berbiaya
const checkoutLimiter = rateLimit({
  windowMs: 60 * 1000,
  limit: 10,
  standardHeaders: "draft-7",
  legacyHeaders: false,
})
router.post("/v1/orders/checkout", checkoutLimiter, checkout)

2. Batasi Ukuran Body

Satu request dengan body 2 GB bisa melumpuhkan. Batasi di parser:

Batasan ukuran body
app.use(express.json({ limit: "1mb" }))
app.use(express.urlencoded({ extended: true, limit: "1mb" }))

3. Verifikasi Manusia di Login

Untuk login, tambahkan CAPTCHA atau challenge setelah beberapa percobaan gagal — menghentikan brute-force otomatis tanpa menghukum user.

Header yang Harus Dikembalikan

Rate limiter modern mengirim header yang berguna bagi client:

text
RateLimit-Limit: 100
RateLimit-Remaining: 95
RateLimit-Reset: 1784149200
Retry-After: 30        # saat kena 429

Client yang paham header ini bisa menyesuaikan diri (backoff) alih-alih terus memukul dan kena 429 — mengurangi beban server.

Trust Proxy

Satu kesalahan paling umum: rate limit membaca IP yang salah karena aplikasi di belakang proxy/load balancer — semua request terlihat dari IP yang sama, dan semua user kena limit bersama.

Beritahu Express tentang proxy
app.set("trust proxy", 1)

Tanpa ini, satu IP proxy mewakili semua user → 429 massal. trust proxy harus diatur saat aplikasi di belakang proxy apa pun (episode 13, 16, 21).

Tip

Ukur lalu tetapkan batas — jangan menebak. Amati traffic normal (episode 11) dan beri margin: jika user sah paling rajin 15 request/menit, batas 50 request/menit aman tanpa melukai siapa pun. Batas yang terlalu rendah lebih berbahaya daripada tidak ada batas: user sah jadi korban.

Common Pitfalls

Rate Limit Hanya di Satu Instance

Counter di memori per instance → scaling melemahkan proteksi. Pakai Redis store sebelum scaling.

429 Tanpa Informasi

Client bingung tanpa pesan dan tanpa Retry-After. Kirim { error, message } + header retry.

Lupa Trust Proxy

Semua user kena limit karena dianggap satu IP. Atur trust proxy.

Rate Limit di WAF Saja

WAF tidak tahu konteks bisnis (per akun, per route). Rate limit aplikasi tetap diperlukan.

Batas Terlalu Ketat untuk Route Umum

Kantor dengan NAT berbagi IP bisa dikunci bersama. Perhitungkan pola penggunaan nyata.

Penutup

Episode 20 mempertahankan ketersediaan: rate limiting per IP dan per akun dengan Redis store, throttling halus untuk user sah, dan strategi DDoS berjenjang dari CDN/WAF, load balancer, hingga rate limit presisi aplikasi.

Inti yang harus dibawa pulang:

  • Batas per akun lebih kuat dari per IP; kombinasikan keduanya.
  • Redis store wajib saat scaling — counter global, bukan per instance.
  • slowDown memperlambat alih-alih menolak — lebih ramah user sah.
  • DDoS ditangani di edge (CDN + WAF), bukan hanya aplikasi.
  • Atur trust proxy dan kembalikan header Retry-After.
  • Tetapkan batas berdasarkan pengukuran, bukan tebakan.

Di episode 21 selanjutnya kita akan membuat sistem tumbuh: scalability & load balancing — scaling horizontal, desain stateless, dan load balancer. Sampai jumpa di episode 21!

Belajar Backend Developer - Rate Limiting & DDoS Protection | Belajar Backend