
Ketika integrasi pembayaran Anda mulai ramai, cepat atau lambat Anda akan bertemu respons yang tidak diinginkan: 429 Too Many Requests. Itu bukan tanda kode Anda rusak, melainkan tanda bahwa Anda menekan API lebih cepat daripada yang diizinkan. Rate limit adalah pagar pengaman yang dipasang setiap penyedia pembayaran untuk menjaga layanan tetap stabil bagi semua pengguna. Kabar baiknya, rate limit bisa diprediksi dan ditangani dengan rapi. Artikel ini membahas apa itu rate limit pada API pembayaran, mengapa ia ada, dan bagaimana membangun klien yang tangguh dengan backoff, antrean, serta idempotensi sehingga transaksi tidak hilang maupun terproses ganda.
Apa Itu Rate Limit dan Kenapa Diperlukan
Rate limit adalah batas jumlah permintaan (request) yang boleh Anda kirim ke sebuah API dalam rentang waktu tertentu, misalnya "100 request per menit" atau "10 request per detik". Batas ini melindungi infrastruktur penyedia dari lonjakan trafik mendadak, mencegah satu klien menghabiskan sumber daya bersama, dan menjaga latensi tetap rendah untuk semua orang.
Ada beberapa alasan rate limit sangat penting di ranah pembayaran:
- Stabilitas — mencegah satu integrasi yang bermasalah (misalnya loop tak berujung) menjatuhkan layanan untuk merchant lain.
- Keamanan — membatasi upaya penyalahgunaan seperti brute-force pada endpoint sensitif.
- Keadilan — memastikan kapasitas dibagi merata antar-pengguna.
Beberapa penyedia menerapkan batas berbeda per endpoint. Endpoint yang mahal secara komputasi (misalnya membuat transaksi) sering punya limit lebih ketat daripada endpoint baca-saja (misalnya cek status). Selalu baca dokumentasi penyedia Anda untuk angka pastinya.
Perlu dipahami pula bahwa rate limit biasanya berlaku per-kredensial, bukan per-server. Artinya jika Anda menjalankan beberapa instance aplikasi yang berbagi satu API key, semuanya menghitung kuota yang sama. Banyak tim terkejut ketika penambahan server justru mempercepat mereka menabrak limit, karena tiap instance berpikir hanya dirinya yang mengirim request. Menyadari batasan ini sejak awal membuat Anda merancang koordinasi laju kirim lintas-instance, bukan sekadar mengandalkan tiap proses berjalan sendiri-sendiri.
Membaca Sinyal dari Server
Kunci menangani rate limit adalah tidak menebak-nebak, melainkan membaca sinyal yang dikirim server. Saat batas terlampaui, API biasanya membalas dengan HTTP status 429. Bersamanya kerap ada header yang sangat berguna:
Retry-After— memberi tahu berapa detik Anda harus menunggu sebelum mencoba lagi. Hormati nilai ini secara eksplisit.X-RateLimit-Limit— total kuota dalam satu jendela waktu.X-RateLimit-Remaining— sisa kuota Anda saat ini.X-RateLimit-Reset— kapan jendela kuota akan direset (sering dalam epoch timestamp).
Dengan memantau X-RateLimit-Remaining, klien pintar bisa memperlambat diri sendiri secara proaktif sebelum benar-benar kena 429. Misalnya, ketika sisa kuota tinggal 10%, aplikasi bisa mulai menyisipkan jeda antar-request alih-alih menabrak dinding limit dan memaksa server menolak.
Strategi Backoff dan Retry yang Benar
Reaksi paling naif terhadap 429 adalah langsung mengulang request. Ini justru memperburuk keadaan karena Anda menambah beban saat server sedang minta Anda mundur. Pendekatan yang benar adalah exponential backoff dengan jitter.
Idenya sederhana: setiap kali gagal, gandakan waktu tunggu, lalu tambahkan sedikit keacakan (jitter) agar banyak klien tidak mencoba ulang serempak di detik yang sama.
- Percobaan 1 gagal: tunggu ~1 detik
- Percobaan 2 gagal: tunggu ~2 detik
- Percobaan 3 gagal: tunggu ~4 detik
- dan seterusnya, hingga batas maksimum yang wajar
Jika header Retry-After tersedia, prioritaskan nilai itu di atas rumus backoff Anda karena server tahu lebih baik kapan ia siap. Tetapkan pula batas jumlah percobaan (misalnya 5 kali) agar sebuah request tidak menggantung selamanya. Prinsip retry ini erat kaitannya dengan cara umum menangani timeout dan retry pada integrasi pembayaran, dan keduanya sebaiknya diterapkan bersama.
Satu hal krusial: retry hanya aman untuk operasi yang idempoten. Jika Anda mengulang pembuatan transaksi tanpa pengaman, pelanggan bisa tertagih dua kali. Di sinilah pentingnya menyertakan kunci idempotensi.
Idempotensi dan Antrean sebagai Jaring Pengaman
Rate limit dan retry akan berbahaya tanpa jaring pengaman terhadap duplikasi. Idempotency key adalah pengenal unik yang Anda kirim bersama request; penyedia menggunakannya untuk mengenali bahwa dua request adalah upaya yang sama, lalu hanya memproses satu kali. Dengan begitu, mengulang request yang sempat kena 429 tidak akan membuat transaksi ganda. Konsep ini dibahas lebih dalam pada panduan idempotency pada API pembayaran.
Untuk trafik tinggi, andalkan antrean (queue) alih-alih menembakkan semua request langsung dari kode aplikasi:
- Buffer lonjakan — masukkan request ke antrean, lalu proses dengan laju terkontrol (rate limiter sisi klien) yang cocok dengan limit penyedia.
- Prioritas — dahulukan operasi penting (misalnya konfirmasi pembayaran) di atas yang bisa ditunda (misalnya sinkronisasi laporan).
- Ketahanan — jika satu request perlu diulang, antrean menyimpannya sehingga tidak ada yang hilang saat proses dijadwal ulang.
Pola sederhana yang efektif adalah token bucket di sisi klien: Anda "mengisi ember" dengan sejumlah token per detik sesuai limit, dan setiap request mengambil satu token. Ketika ember kosong, request menunggu. Cara ini menjaga laju kirim Anda selalu di bawah batas server sehingga 429 nyaris tak pernah terjadi.
Perlu diingat, tidak semua kegagalan harus diperlakukan sama. Bedakan antara error yang layak diulang dan yang tidak. Status 429 dan sebagian error server 5xx umumnya aman untuk retry karena sifatnya sementara. Sebaliknya, error 4xx seperti 400 (permintaan salah) atau 401 (otentikasi gagal) tidak akan membaik dengan pengulangan; mengulangnya hanya membuang kuota dan menunda perbaikan sesungguhnya. Klien yang matang mengategorikan respons terlebih dahulu, lalu memutuskan: ulang dengan backoff, gagalkan segera, atau alihkan ke penanganan manual.
Memantau dan Menskalakan dengan Aman
Menangani rate limit bukan hanya soal kode, tetapi juga observabilitas. Catat (log) setiap respons 429 beserta endpoint, waktu, dan header kuota. Dari sana Anda bisa melihat pola: apakah lonjakan terjadi pada jam sibuk, atau apakah satu proses batch menghabiskan kuota. Beberapa langkah praktis:
- Pisahkan trafik latar belakang (laporan, rekonsiliasi) dari trafik real-time (checkout) agar batch tidak "memakan" kuota pembayaran pelanggan.
- Cache data yang jarang berubah supaya Anda tidak memanggil API berulang untuk informasi yang sama.
- Jadwalkan pekerjaan berat di luar jam puncak.
- Jika volume Anda benar-benar tumbuh, hubungi penyedia untuk menanyakan kenaikan limit; ini hal wajar bagi merchant yang berkembang.
BorderPay adalah lapisan teknologi (software) di atas mitra Payment Gateway yang berlisensi Bank Indonesia; pemrosesan dan penyimpanan dana dilakukan oleh mitra berlisensi tersebut. Artinya, saat Anda memanggil API, ada batas wajar yang berlaku baik di lapisan software maupun di sisi mitra. Dengan mendesain klien Anda untuk menghormati header limit, menerapkan backoff, dan menjaga idempotensi, integrasi Anda akan tetap stabil bahkan ketika trafik melonjak.
Rate limit sejatinya bukan hambatan, melainkan kontrak keandalan antara Anda dan penyedia. Bangun klien yang membaca sinyal server, mundur dengan sopan saat diminta, dan tidak pernah menduplikasi transaksi. Jika Anda ingin fondasi integrasi yang sudah menyertakan idempotensi dan pola retry sejak awal, dokumentasi teknis BorderPay bisa menjadi titik mulai yang jujur dan ramah developer.