Rate Limiting
PortalData menerapkan rate limiting untuk memastikan stabilitas dan keadilan penggunaan API. Pelajari batas request berdasarkan tier langganan Anda.
Cara Kerja Rate Limiting
Rate limiting diterapkan menggunakan algoritma sliding window untuk memberikan pengalaman yang lebih baik dibanding fixed window. Setiap API key memiliki batas berdasarkan tier langganan perusahaan.
Jenis Pembatasan
Batas Request per Tier
Setiap tier memiliki batas request yang berbeda:
| Tier | Request/Menit | Request/Hari | Request/Bulan | Burst Allowance |
|---|---|---|---|---|
| Free | 10 | 100 | 1.000 | 20 |
| Starter | 100 | 2.000 | 50.000 | 200 |
| Growth | 500 | 20.000 | 500.000 | 1.000 |
| Enterprise | 2.000 | 100.000 | Unlimited | 5.000 |
Apa itu Burst Allowance?
Burst allowance memungkinkan Anda mengirim request lebih dari batas per menit untuk waktu singkat. Ini berguna untuk skenario batch processing atau initial data fetch.
Response Headers
Setiap response API menyertakan headers yang menunjukkan status rate limit Anda:
| Header | Deskripsi | Contoh |
|---|---|---|
X-RateLimit-Limit | Batas request per menit untuk tier Anda | 100 |
X-RateLimit-Remaining | Sisa request yang tersedia di window saat ini | 95 |
X-RateLimit-Reset | Unix timestamp kapan limit akan reset | 1706054460 |
X-RateLimit-Policy | Kebijakan rate limit (limit;window) | 100;w=60 |
Retry-After | Detik menunggu sebelum retry (hanya saat 429) | 30 |
Contoh Response Headers
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1706054460
X-RateLimit-Policy: 100;w=60Ketika Limit Terlampaui
Saat rate limit terlampaui, API akan mengembalikan HTTP status 429:
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Upgrade your plan for higher limits.",
"retry_after": 30,
"upgrade_url": "https://portaldata.id/pricing"
}{
"error": "monthly_limit_exceeded",
"message": "Monthly request limit of 1000 exceeded. Please upgrade your plan."
}Handling Rate Limits
Contoh kode untuk menangani rate limiting dengan baik:
async function fetchWithRetry(url, options, maxRetries = 3) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, {
...options,
headers: {
'X-API-Key': process.env.PORTALDATA_API_KEY,
...options.headers
}
});
// Jika rate limited, tunggu dan retry
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '30');
console.log(`Rate limited. Waiting ${retryAfter}s before retry...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
// Log rate limit info untuk monitoring
const remaining = response.headers.get('X-RateLimit-Remaining');
if (remaining && parseInt(remaining) < 10) {
console.warn(`Low rate limit remaining: ${remaining}`);
}
return response;
} catch (error) {
lastError = error;
// Exponential backoff untuk network errors
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}import time
import requests
from functools import wraps
class PortalDataClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://api.portaldata.id/api/v1'
self.session = requests.Session()
self.session.headers['X-API-Key'] = api_key
def _request(self, method, endpoint, **kwargs):
url = f'{self.base_url}{endpoint}'
max_retries = 3
for attempt in range(max_retries):
response = self.session.request(method, url, **kwargs)
# Track rate limit
remaining = response.headers.get('X-RateLimit-Remaining')
if remaining:
print(f'Rate limit remaining: {remaining}')
# Handle rate limit
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 30))
print(f'Rate limited. Waiting {retry_after}s...')
time.sleep(retry_after)
continue
return response
raise Exception('Max retries exceeded')
def get_regions(self, **params):
return self._request('GET', '/regions', params=params).json()
def get_kbli(self, code):
return self._request('GET', f'/kbli/{code}').json()
# Penggunaan
client = PortalDataClient(api_key='pk_live_xxx')
regions = client.get_regions(level='province')Best Practices
Implementasi Caching
Cache response untuk data yang jarang berubah (seperti wilayah, KBLI). Ini mengurangi jumlah request dan mempercepat aplikasi.
Monitor Rate Limit Headers
Pantau header X-RateLimit-Remaining dan beri peringatan jika mendekati limit. Ini membantu mencegah gangguan layanan.
Gunakan Exponential Backoff
Saat mendapat error 429, jangan langsung retry. Gunakan exponential backoff atau nilai dari header Retry-After.
Batch Requests Jika Memungkinkan
Gabungkan beberapa request menjadi satu jika API mendukung. Misalnya, gunakan include=children daripada request terpisah.
Butuh Limit Lebih Tinggi?
Jika aplikasi Anda membutuhkan limit yang lebih tinggi, pertimbangkan untuk upgrade tier: