Menguji Rate Limit API untuk Mencegah Penyalahgunaan dan Pembengkakan Biaya
Ukur pekerjaan lalu terapkan budget
Review konsumsi resource dimulai dari pengukuran biaya. Profilkan pembuatan laporan, verifikasi password, fan-out pencarian, konversi gambar, retry webhook, serta pesan ke provider berbayar. Tentukan key yang mewakili budget adil: akun, tenant, credential API, perangkat, IP, worker queue, atau akun provider. Satu counter request global tidak dapat menjelaskan seluruh biaya tersebut.
Jalankan pengujian terkontrol pada baseline, tepat di bawah ambang, ambang, dan ambang konkurensi. Limit ekspor CSV baru lulus bila job berikutnya memperoleh perilaku queue atau 429 yang terdokumentasi serta tidak membuat objek storage, snapshot database, atau biaya provider. Periksa route alternatif dan encoding parameter; cap /reports/export yang dapat dilewati lewat /reports?format=csv bukan perlindungan. Untuk GraphQL, complexity dan ukuran batch dapat menjadi dimensi budget, bukan jumlah request.
Catatan kegagalan memuat metrik biaya, key kuota, window, output retry, kedalaman queue, dan jumlah panggilan downstream. Perbaikan dapat berupa input maksimum sebelum parsing, concurrency per tenant, idempotency key, atau circuit breaker pada provider berbayar. Uji penutup membuktikan pekerjaan tertolak tidak memiliki side effect parsial dan trafik normal pulih setelah window reset; owner kapasitas memilih ambang dari limit layanan yang terukur.
Enforcement budget memerlukan observabilitas tanpa membocorkan detail internal kepada pemanggil. Hitung unit yang diterima dan ditolak, waktu tunggu queue, jumlah request downstream, serta hasil retry per operasi. Bedakan retry klien setelah timeout dari request mahal baru dengan idempotency key. Uji burst harus berhenti pada ceiling yang disetujui dan mencakup verifikasi cleanup. Bila kuota pihak ketiga lebih rendah daripada kuota gateway, batas provider berlaku; konfigurasi circuit agar kegagalan tidak menciptakan badai retry.
Memilih dimensi kuota dari biaya
Rate limit dimulai dari perhitungan pekerjaan. Daftarkan aksi mahal: pemeriksaan password, pembuatan laporan, konversi gambar, fan-out pencarian, unduhan file, retry webhook, serta SMS atau email berbayar. Untuk tiap aksi, tentukan unit yang menanggung biaya. Percobaan login dapat memakai akun dan IP; job laporan dapat memakai tenant dan jumlah worker bersamaan; pencarian publik dapat memakai credential dan complexity query. Counter per-IP saja tidak menghentikan trafik terdistribusi maupun memperlakukan kantor bersama secara adil.
Ukur durasi baseline, pembacaan database, penggunaan worker, byte respons, kedalaman queue, dan request eksternal memakai fixture sintetis. Jalankan empat kasus terkontrol: trafik normal, tepat pada kuota, satu request di atas kuota, serta banyak pemanggil paralel. Untuk POST /reports/export, hasil di atas kuota harus 429 terdokumentasi atau penolakan queue. Hasil tidak boleh membuat file object storage, job queue tersimpan, atau biaya provider. Catat header retry dan perilaku reset; klien tidak boleh diberi waktu retry sebelum server menerimanya.
Uji terdistribusi dan identitas
Gunakan beberapa IP untuk satu akun, beberapa akun dari satu IP, beberapa credential dalam satu tenant, serta satu credential melalui beberapa route yang memicu pekerjaan downstream sama. Kasus ini menunjukkan apakah key kebijakan sesuai model abuse. Penyerang dapat membagi alamat sumber sambil menghabiskan budget laporan satu tenant; NAT bersama dapat membawa banyak pengguna sah. Uji bentuk endpoint alternatif seperti /exports dan /reports?format=csv, agar limit operasi tidak dilewati lewat representasi lain.
Saat burst berlangsung, batalkan beberapa klien di tengah jalan. Slot worker, file sementara, dan upload parsial harus dilepas. Ulangi dengan idempotency key dan pastikan kapasitas tidak dipesan dua kali. Queue bukan limit bila backlog tidak dibatasi atau tugas yang ditolak tetap menumpuk. Bila kuota provider lebih rendah daripada kuota aplikasi, hasil provider menjadi batas gagal dan circuit harus mencegah badai retry.
Bukti dan penutupan
Simpan versi konfigurasi kuota, parameter skrip trafik, dimensi identitas, timestamp, sampel latensi, ukuran queue, jumlah panggilan provider, serta hasil cleanup. Owner kapasitas memilih ambang dari headroom terukur dan target pemulihan, lalu menyetujui aturan operasional. Perbaiki dengan cap ukuran request sebelum parsing, cap pagination, concurrency per tenant, budget token, idempotency, atau circuit breaking provider. Penutupan menjalankan ulang kasus ditolak, membuktikan tidak ada side effect parsial, lalu menjalankan kasus diizinkan setelah window reset. Pengecualian integrasi lama menyebut route, kuota, konsumen, tanggal akhir, dan sinyal monitoring; pengecualian tidak pernah mematikan seluruh limit.
Perilaku pemulihan
Limit juga merupakan keputusan ketersediaan. Pastikan request biasa pulih ketika window direset dan satu pemanggil ditolak tidak mengunci pekerjaan tenant lain. Periksa clock skew antara counter gateway dan aplikasi; waktu reset tidak konsisten membuat klien melakukan retry beruntun. Saat counter tidak tersedia, tetapkan fail-open atau fail-closed untuk tiap operasi. Login dan pesan berbayar mungkin membutuhkan penolakan konservatif, sedangkan baca publik berbiaya rendah dapat menoleransi degradasi. Catat pilihan tersebut bersama bukti biaya.
Jalankan skrip terdistribusi cukup lambat untuk mengamati setiap lapisan. Bandingkan counter gateway, budget aplikasi, admission queue, dan respons provider. Jika lapisan berbeda, putuskan mana yang memberi penolakan otoritatif lalu buat respons deterministik. Uji penghapusan tenant atau rotasi credential: entri kuota lama tidak boleh memberi principal baru kapasitas tak diharapkan. Artefak akhir memuat konfirmasi cleanup file sementara, job, serta pesan test provider.
Catatan eksekusi budget resource
| Operasi dan kuota | Owner | Bukti | Hasil yang diharapkan | Hasil teramati / status | Pengecualian | Penutupan |
|---|---|---|---|---|---|---|
POST /reports/export; 5 job bersamaan per tenant | Owner kapasitas | Run RL-206; konfigurasi kuota v12; counter queue, storage, dan provider | Request keenam mendapat 429 tanpa job, file, atau panggilan provider | 429; delta queue 0; file 0; panggilan provider 0 — ditutup | Tidak ada | Request valid lulus setelah reset; file sementara dibersihkan; run disetujui 2026-06-12 |