Rate limit + Idempotency

Güvenli retry, sıfır duplicate

Redis-backed rate limit (fail-open), 24h Idempotency-Key window, (sourceId, externalId) DB unique. Reddedilen event'ler IntegrationDeadLetter'a düşer ve internal API'den replay edilebilir.

Rate limit

Redis-backed, fail-open

Her partner anahtarı dakikada 60 istek için scope'lanmıştır (yüksek hacim ihtiyacınız varsa biz açabiliriz). Sayım Redis üzerinden yapılır; Redis erişilemezse rate limit fail-open davranır — yani trafik durmaz, WARN log yazılır.

  • X-RateLimit-Remaining her response'ta gelir — proaktif throttle için kullanın.
  • • 429 alırsanız Retry-After saniyesi kadar bekleyin, Idempotency-Key'i aynı tutun.
  • X-RateLimit-Reset unix timestamp, pencerenin sıfırlanma zamanı.
başarılı istek
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1747298500
X-RateLimit-Window: 60s

…response body…
limit aşıldı
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1747298500

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests — retry after 12 seconds",
    "requestId": "req_01J9XZ…"
  }
}
Idempotency-Key akışı
POST /api/integrations/v1/sales HTTP/1.1
X-Integration-Key: biint_live_…
Idempotency-Key: 0e1a4b2f-5c33-4d61-aa11-2b3c5d6e7f8a

# İlk istek → 202 Accepted, kaydedilir.
# 30 saniye sonra aynı key + aynı payload:
# 200 OK ile orijinal response replay edilir (DB'ye yeni satır yazılmaz).
# Aynı key + FARKLI payload:
# 409 IDEMPOTENCY_CONFLICT.

Idempotency

İki katmanlı duplicate koruma

Network glitch'lerinden, retry'lardan ve crash recovery'den dolayı aynı event'i iki kez göndermek normal. partner-api iki katmanda koruma sağlar:

  1. 1. HTTP — Idempotency-Key header
    UUID v4 önerilir. 24 saatlik Redis cache window. Aynı key + aynı payload = orijinal response replay. Aynı key + farklı payload = 409.
  2. 2. DB — (sourceId, externalId) unique
    Header olmadan bile partner-api (anahtarınızın bağlı olduğu sourceId, sizin externalId'niz) çiftini DB-unique tutar. İkinci yazımda 200 + replay.

Dayanıklılık

Outbox + DLQ ile sıfır veri kaybı

Controller'lar asla doğrudan RabbitMQ'ya yazmaz. Audit satırı + outbox satırı tek $transaction içinde yazılır; arka plan worker'ı FOR UPDATE SKIP LOCKED ile drain eder. biHesap-api veya RabbitMQ down olursa veri kaybı olmaz — sadece publish gecikir.

60 req/min

Anahtar başına varsayılan rate limit. Yüksek hacim için artırma talebi gönderin.

24h cache

Idempotency-Key Redis cache window. Sonrasında DB-unique hâlâ korur.

Outbox drain

Worker outbox satırlarını publisher confirms ile RabbitMQ'ya gönderir. Çoklu replica-safe.

DLQ replay

Reddedilen event'ler IntegrationDeadLetter'a düşer; biHesap panelinden tek tıkla replay edilir.