Cara Kerja Rate Limiting di Email API: Panduan Developer untuk Hindari Error 429

Rate limiting adalah mekanisme kontrol yang membatasi jumlah request ke API dalam periode waktu tertentu. Di Mailketing API v2, implementasi rate limiting sengaja dirancang berbeda dari kebanyakan API lain — memahami cara kerjanya akan membantu developer menghindari error 429 dan merancang integrasi yang lebih robust.

Cara Kerja Rate Limiting di Mailketing API v2

Perbedaan utama Mailketing API v2 dibanding API lain: rate limit hanya berlaku untuk request yang gagal, bukan semua request.

Jenis RequestBatasWindowBerlaku per
Request gagal (401/402/403/404/422/500)30 request1 menitIP address
Request sukses (200)Tidak dibatasi

Artinya: jika sistem mengirim 10.000 email per jam dengan sukses, tidak akan kena rate limit sama sekali. Rate limit baru aktif jika ada bug atau kesalahan konfigurasi yang menyebabkan banyak request gagal berturut-turut.

Kenapa Hanya Request Gagal yang Di-rate Limit?

Desain ini melindungi server Mailketing dari dua skenario berbahaya:

  • Credential stuffing — serangan yang mencoba ribuan kombinasi token API secara otomatis. Dengan rate limit di request gagal (401), serangan ini terhenti setelah 30 percobaan per menit per IP.
  • Looping error di kode — bug di sisi developer yang menyebabkan retry tak terbatas untuk request yang memang akan selalu gagal (misalnya sender belum diverifikasi, kredit habis). Rate limit memaksa developer untuk memperbaiki root cause, bukan terus-terusan retry.

Untuk pengiriman email yang sah (request sukses), tidak ada throttling — sesuai dengan kebutuhan sistem email transaksional yang harus bisa mengirim dalam volume besar dan cepat.

Response Headers Rate Limit

Setiap response dari Mailketing API v2 menyertakan header berikut untuk membantu developer memantau status rate limit:

# Header di setiap response (sebelum kena limit)
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 27

# Header saat kena 429
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
Retry-After: 42

Retry-After menunjukkan berapa detik harus menunggu sebelum boleh mencoba lagi. Nilainya dinamis tergantung kapan window 1 menit reset.

Contoh Response 429

{
  "success": false,
  "data": null,
  "message": "Too Many Requests",
  "errors": {}
}

Implementasi Handling Rate Limit di Berbagai Bahasa

PHP

function sendEmailWithRetry(array $payload, int $maxRetries = 3): array {
    $attempt = 0;
    while ($attempt  true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'X-Api-Token: ' . $_ENV['MAILKETING_TOKEN'],
            ],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER => true,
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $headers = substr($response, 0, $headerSize);
        $body = json_decode(substr($response, $headerSize), true);
        curl_close($ch);

        if ($httpCode === 429) {
            // Baca Retry-After dari header
            preg_match('/Retry-After:s*(d+)/i', $headers, $matches);
            $waitSeconds = isset($matches[1]) ? (int)$matches[1] : 60;
            sleep($waitSeconds);
            $attempt++;
            continue;
        }

        return ['code' => $httpCode, 'body' => $body];
    }
    throw new RuntimeException('Max retries reached after rate limiting');
}

JavaScript / Node.js

async function sendEmailWithRetry(payload, maxRetries = 3) {
  for (let attempt = 0; attempt  setTimeout(resolve, retryAfter * 1000));
      continue;
    }

    return { code: res.status, body: await res.json() };
  }
  throw new Error('Max retries reached after rate limiting');
}

Python

import requests
import time
import os

def send_email_with_retry(payload: dict, max_retries: int = 3) -> dict:
    url = 'https://api.mailketing.co.id/api/v2/send'
    headers = {
        'Content-Type': 'application/json',
        'X-Api-Token': os.environ['MAILKETING_TOKEN'],
    }

    for attempt in range(max_retries):
        response = requests.post(url, json=payload, headers=headers)

        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            print(f'Rate limited. Waiting {retry_after}s...')
            time.sleep(retry_after)
            continue

        return {'code': response.status_code, 'body': response.json()}

    raise Exception('Max retries reached after rate limiting')

Best Practice Menghindari 429

Karena rate limit hanya berlaku untuk request gagal, strategi utama bukan soal membatasi kecepatan pengiriman — tapi memastikan request tidak gagal sejak awal:

  • Validasi token sebelum deploy — pastikan environment variable MAILKETING_TOKEN ter-set dengan benar di semua environment (development, staging, production)
  • Monitor saldo kredit — panggil GET /credits secara berkala, kirim alert internal jika kredit mendekati 0 untuk mencegah error 402 massal
  • Verifikasi sender sebelum go-live — pastikan semua from_email yang akan digunakan sudah berstatus verified via GET /senders
  • Jangan retry tanpa kondisi — implementasikan circuit breaker: jika 5 request gagal berturut-turut dengan kode yang sama (misalnya 402), hentikan retry dan kirim alert ke tim
  • Log semua error response — baca field errors di response 422 untuk debug validasi input

Perbedaan Rate Limit Mailketing vs API Lain

AspekAPI UmumMailketing API v2
Yang di-rate limitSemua requestHanya request gagal
Dampak pada pengiriman normalBisa terhambat saat volume tinggiTidak terhambat
Tujuan utamaProteksi server dari bebanProteksi dari abuse dan looping error
Header informasiX-RateLimit-Limit/RemainingX-RateLimit-Limit/Remaining + Retry-After

FAQ

Apakah rate limit berlaku per akun atau per IP?

Per IP address. Jika aplikasi di-deploy di beberapa server dengan IP berbeda, setiap IP mendapat kuota 30 request gagal per menit secara independen.

Apakah bisa request indexing ulang setelah kena 429?

Ya. Setelah window 1 menit reset, kuota request gagal kembali ke 30. Gunakan nilai Retry-After di response header untuk tahu kapan harus mencoba lagi.

Apakah kirim 10.000 email sekaligus akan kena rate limit?

Tidak, selama semua request berhasil (response 200). Rate limit hanya aktif jika request gagal. Untuk volume pengiriman tinggi yang sukses, tidak ada throttling dari sisi Mailketing.

Bagaimana cara test rate limit tanpa mengganggu produksi?

Gunakan token API yang salah (token dummy) di environment testing untuk memicu error 401 berulang kali hingga kena 429. Ini cara aman untuk menguji implementasi retry logic tanpa menyentuh data produksi.


Butuh akses ke Mailketing API v2 untuk diintegrasikan ke sistemmu? Daftar Mailketing gratis dan dapatkan API token langsung — kirim email transaksional, OTP, atau notifikasi dari aplikasimu dalam hitungan menit.

Related Articles​