Prompt dan konteks
Pertanyaan ini menguji apakah "N permintaan per menit" dapat diubah menjadi control plane dan data plane yang dapat dioperasikan. Limiter melindungi kapasitas sekaligus menjaga keadilan dan prioritas bisnis; node terdistribusi dan shared state memicu adanya aproksimasi. Bahas kebijakan, algoritma, penyimpanan, respons, fallback, peluncuran (rollout), dan metrik.
Yang diuji oleh pewawancara
Jawaban yang kuat mengklarifikasi dimensi, jendela waktu (window), burst, dan semantik kegagalan sebelum membandingkan token bucket, leaky bucket, fixed window, dan sliding window. Mereka memisahkan distribusi kebijakan dari keputusan saat permintaan datang, menjelaskan atomic counter, hot key, perilaku multi-region, serta kegagalan Redis, dan mengembalikan sinyal Retry-After yang dapat ditindaklanjuti. Mereka juga mendiskusikan peluncuran bayangan (shadow rollout), error budget, dan bypass yang diaudit.
Pertanyaan untuk diklarifikasi
- Apakah kuncinya adalah API, tenant, pengguna, IP, atau kombinasinya? Apakah pelanggan premium diprioritaskan?
- Apakah kita mengontrol laju berkelanjutan (sustained rate), ukuran burst, konkurensi, atau beberapa sumber daya sekaligus?
- Apakah permintaan yang berlebih akan gagal, mengantre, didegradasi, atau menerima sedikit kelebihan kuota (overage)? Apakah konsistensi global diperlukan?
- Jika limiter tidak tersedia, apakah sistem harus fail-open atau fail-closed? Rute mana saja yang berisiko tinggi?
- Seberapa sering kebijakan berubah, dan apakah kita memerlukan peluncuran bertahap, audit, rollback, serta efek langsung seketika?
Kerangka jawaban 30 detik
"Saya akan memisahkan kontrol kebijakan dari keputusan saat permintaan tiba. Normalisasi tenant, pengguna, dan rute menjadi sebuah kunci; data plane menjalankan token bucket atomik di Redis Lua serta mengembalikan sisa kuota dan waktu coba lagi. Kebijakan berversi di-cache, di mana cache lokal dapat melakukan penolakan cepat tetapi shared state membuat keputusan akhir. Selama pemadaman singkat pada shared-store, rute berisiko rendah menggunakan anggaran darurat tenant dan menerapkan fail-open; rute berisiko tinggi menerapkan fail-closed dan mengirimkan page. Mode shadow, burn rate, metrik hot-key, dan batas kesalahan regional memandu peluncuran."
Jawaban mendalam langkah demi langkah
Langkah 1: Tentukan kapasitas dan keadilan
Pisahkan laju berkelanjutan, ukuran burst, dan konkurensi. Kuota tenant mencegah satu pelanggan menghabiskan pool global; kuota pengguna mengisolasi kebisingan (noise) di dalam tenant. Rute kritis dapat menerima anggaran khusus. Keadilan adalah kebijakan bisnis, bukan bawaan algoritma yang terjadi secara kebetulan.
Langkah 2: Pilih algoritma
Token bucket mengizinkan burst terkontrol dan cocok untuk API; leaky bucket memuluskan output; sliding window intuitif tetapi membutuhkan lebih banyak state. Saat state dibagi di Redis, gunakan Redis TIME di dalam skrip atomik agar setiap node menggunakan jam yang sama, batasi waktu yang berlalu minimal nol (clamp at zero), serta tentukan pembersihan state dan batas presisi.
Langkah 3: Modelkan kunci dan kebijakan
Normalisasi method, rute, tenant, principal, dan region agar setiap node menghasilkan kunci yang sama. Suatu kebijakan mencakup batas, burst, cakupan, prioritas, versi, waktu efektif, dan pemilik. Kebijakan yang tidak dikenal akan kembali ke baseline yang aman; klien tidak dapat menentukan kuotanya sendiri.
Langkah 4: Buat keputusan bersifat atomik
Satu operasi bersama membaca state, mengisi ulang token, memotong biaya, dan memperbarui TTL. Redis Lua, operasi basis data atomik, atau sidecar dapat digunakan; kuncinya adalah menghindari race condition read-then-write. Kembalikan sisa token, waktu reset, dan versi kebijakan.
Langkah 5: Tangani hot key dan region
Tenant yang populer dapat mengubah satu kunci menjadi hotspot. Shard anggarannya dan gabungkan di koordinator hanya jika batas kelebihan kuota dapat diterima. Sistem multi-region dapat menggunakan kuota regional dan agregasi global secara asinkron; konsistensi global yang ketat mengorbankan ketersediaan dan latensi.
Langkah 6: Rancang kegagalan dan fallback
Pilih fail-open atau fail-closed berdasarkan risiko rute dan tetapkan anggaran darurat lokal. Ketika penyimpanan kebijakan tidak tersedia, gunakan versi terakhir dengan TTL pendek. Pemulihan tidak boleh melepaskan semua akumulasi permintaan sekaligus. Audit setiap bypass dan keputusan yang didegradasi.
Langkah 7: Luncurkan perubahan
Jalankan kebijakan baru dalam mode shadow terlebih dahulu, bandingkan prediksi penolakan, lalu aktifkan berdasarkan tenant atau persentase. Sertakan versi kebijakan dalam log dan siapkan mekanisme rollback. Setiap pengecualian sementara memerlukan pemilik dan masa kedaluwarsa.
Langkah 8: Ukur hasil
Pantau rasio allow/deny, sisa kuota, latensi keputusan p95, hot key, kesalahan penyimpanan, versi kebijakan, banding penolakan salah (false-reject), dan kelebihan beban backend. Hubungkan metrik tersebut dengan 5xx, kedalaman antrean, dan latensi ekor (tail latency); pembatasan yang terlalu longgar gagal melindungi sistem, pembatasan yang terlalu ketat merugikan bisnis.
Pseudocode token-bucket atomik
now = redis_time()
state = load(key) or {tokens: burst, at: now}
elapsed = max(0, now - state.at)
state.tokens = min(burst, state.tokens + elapsed * rate)
allowed = state.tokens >= cost
if allowed:
state.tokens -= cost
state.at = now
save_atomically(key, state, ttl)
return allowed, state.tokens, retry_after(state)Trade-off dan batasan
| Pilihan | Cocok untuk | Biaya utama |
|---|---|---|
| Token bucket | API dengan traffic burst | Shared atomic state |
| Local limiter | Perlindungan dengan latensi terendah | Kuota multi-node tidak presisi |
| Kuota regional | Ketersediaan multi-region | Error keadilan global |
| Fail-closed | Pembayaran dan autentikasi | Pemadaman limiter memengaruhi ketersediaan |
Rate limiting bukanlah antrean ataupun pengganti untuk perencanaan kapasitas, circuit breaking, atau autentikasi. Antrean cocok untuk permintaan yang dapat menunggu; limiter menolak dengan cepat di batas sumber daya daripada menyembunyikan kelebihan beban sebagai latensi.
Rencana peluncuran dan bukti
Bangun model kebijakan dan data plane token-bucket untuk satu API bervolume tinggi, jalankan mode shadow selama satu hari, lalu aktifkan untuk beberapa tenant. Microsoft Well-Architected memperlakukan throttling sebagai kontrol kelebihan beban aktif; materi DataInterview dan System Design School menekankan pilihan algoritma, shared state, dan Retry-After.
Kriteria keluar tahap pilot
Setelah simulasi untuk lonjakan lalu lintas, kegagalan shared-store, rollback, dan tenant yang padat, target latensi tetap terpenuhi; setiap penolakan yang salah memiliki alasan; anggaran fallback berfungsi; serta kebijakan memiliki pemilik, versi, dan catatan audit.
Cara membuktikan keberhasilannya nyata
Bandingkan kelebihan beban backend, 5xx, latensi p99, rasio penolakan, rasio penolakan salah, dan biaya penyimpanan sebelum dan sesudah penerapan, yang disegmentasikan berdasarkan tenant, rute, dan region. Lakukan normalisasi terhadap kapasitas agar periode lalu lintas rendah alami tidak disalahartikan sebagai keberhasilan.
Kesalahan umum dan pertanyaan lanjutan
Counter lokal di setiap node sudah cukup
Setiap node melepaskan kuotanya sendiri, sehingga klien dapat melebihi batas dengan berpindah-pindah node. Kuantifikasi aproksimasi tersebut atau gunakan shared state/anggaran regional untuk rute kritis.
Hanya menggunakan fixed window
Batas jendela waktu memungkinkan terjadinya double burst singkat. Gunakan token bucket atau sliding window dan jelaskan biaya state serta presisinya.
Mengizinkan semua permintaan lewat saat limiter gagal
Rute berisiko tinggi kehilangan perlindungan terakhirnya. Pilih anggaran darurat dan terapkan fail-open/closed berdasarkan risiko, disertai peringatan paging.
Bagaimana cara menghindari dampak buruk pada tenant premium?
Konfigurasikan kuota dan prioritas tenant, pisahkan pool bersama dan pool bergaransi, serta berikan masa kedaluwarsa dan jejak audit pada setiap pengecualian.
Bagaimana seharusnya klien mencoba lagi?
Patuhi Retry-After, gunakan backoff dengan jitter, dan jangan pernah mengulang 429 tanpa henti. Percobaan ulang otomatis memerlukan permintaan yang idempoten.
Bagaimana cara melakukan canary untuk kebijakan baru?
Kalkulasikan dalam mode shadow, aktifkan berdasarkan tenant atau persentase, bandingkan penolakan, konversi, dan beban backend, serta buat versi pada kebijakan untuk kemudahan rollback.