Ayarlar

Dil

AI API Rate Limiting: Nasıl Çalışır ve Nasıl Başa Çıkılır?

L
LemonData
·26 Şubat 2026·654 görüntüleme
AI API Rate Limiting: Nasıl Çalışır ve Nasıl Başa Çıkılır?

Her AI API'sinin hız sınırları (rate limits) vardır. Bunlarla geliştirme aşamasında karşılaşmak can sıkıcıdır. Üretim (production) aşamasında karşılaştığınızda ise kullanıcılarınız, siz deseni inceleyene kadar rastgele görünen hatalar, kısmi akışlar (streams) ve zaman aşımları (timeouts) görürler.

Temel hata, hız sınırlamayı tek bir sorun olarak görmektir. Genellikle aynı 429 hatasının arkasına gizlenmiş dört farklı sorun vardır:

  • dakika başına istek (requests per minute)
  • dakika başına token (tokens per minute)
  • eşzamanlı aktif istekler (concurrent in-flight requests)
  • hesap düzeyinde veya proje düzeyinde kota tükenmesi (quota exhaustion)

Bunlardan sadece biri için çözüm üretirseniz, diğerleri canınızı yakmaya devam eder.

Eğer hala sağlayıcı değiştirme aşamasındaysanız, önce migration guide (geçiş kılavuzu) içeriğini okuyun. Eğer bir gateway'in fallback ve operasyonel yük konusunda yardımcı olup olmayacağını değerlendiriyorsanız, OpenRouter comparison (OpenRouter karşılaştırması) en iyi yardımcı okuma olacaktır.

Hız Sınırları (Rate Limits) Gerçekte Ne Anlama Gelir?

İstek sınırları (Request limits)

Bu en bariz olanıdır. Kısa bir zaman diliminde çok fazla istek gönderdiniz.

Token sınırları (Token limits)

Bu, ekiplerin genellikle küçümsediği sınırdır. Tek bir uzun prompt, birçok küçük istek kadar bütçe tüketebilir. Aniden 20 KB'lık bir sistem prompt'u eklerseniz, istek sayınız sağlıklı görünse bile token bütçeniz çoktan bitmiş olabilir.

Eşzamanlılık sınırları (Concurrency limits)

Bazı sağlayıcılar ve gateway'ler, aynı anda elli akış (stream) açana kadar dakika başına ortalamanızdan gayet memnun kalırlar. Hız planınız (rate plan) uygundur ancak anlık yüklenme (burst) şekli uygun değildir.

Kota veya bakiye tükenmesi (Quota or balance exhaustion)

Bu durum genellikle dashboard'larda bir "hız sınırı" belirtisi olarak ortaya çıkar çünkü operasyonel sonuç aynıdır: çağrılar başarılı olmaz. Ancak çözüm farklıdır. Sorun sıfır bakiye ise backoff (bekleyip tekrar deneme) işe yaramaz.

Sağlayıcılar Sınırları Genellikle Nasıl Uygular?

Kesin rakamlar zamanla değişir, bu nedenle uygulama dokümanlarınıza sabit bir fiyat tablosu grafiği eklemek zamanla geçerliliğini yitirir. Kararlı olan desen şudur:

  • OpenAI tarzı sağlayıcılar genellikle istek ve token header'larını gösterir ve tavan sınırınızı hesap geçmişine veya kullanım katmanına göre ayarlar.
  • Anthropic tarzı sağlayıcılar, özellikle üst düzey modellerde hem dakika düzeyinde throughput (iş çıkarma kapasitesi) hem de daha geniş proje sınırları uygular.
  • Google tarzı sağlayıcılar genellikle ücretsiz katman davranışını ücretli katman davranışından ayırır ve sınırları model ailesine göre keskin bir şekilde değiştirebilir.
  • Aggregator'lar (toplayıcılar), kaynak sağlayıcı kısıtlamalarının üzerine bir sınır katmanı daha ekler, ancak buna karşılık bir kaynak geçici olarak doygunluğa ulaştığında diğer kanallara yönlendirme yapabilirler.
  • Sağlayıcı sınırlarını sabit değerler olarak değil, canlı konfigürasyonlar olarak değerlendirin.

Hız Sınırı (Rate Limit) Header'larını Okumak

Tüm büyük sağlayıcılar, yanıt header'larında hız sınırı bilgilerini döndürür:

x-ratelimit-limit-requests: 500
x-ratelimit-remaining-requests: 499
x-ratelimit-reset-requests: 60s
x-ratelimit-limit-tokens: 200000
x-ratelimit-remaining-tokens: 199500

Bu header'ları proaktif olarak kullanın. Yavaşlamak için bir 429 hatası almayı beklemeyin.

İstediğiniz operasyonel alışkanlık basittir:

  1. Header'ları sadece hata durumunda değil, başarı durumunda da loglayın.
  2. Kalan kapasite bir eşiğin altına düştüğünde uyarı (alert) verin.
  3. Bir sonraki istek sınırı aşmadan önce trafiği şekillendirin.

Header'lara sadece bir hatadan sonra bakarsanız, zaten geride kalmışsınız demektir.

Yeniden Deneme (Retry) Mantığı Oluşturma

Yanlış Yöntem

# Bunu yapmayın
import time

def call_api(messages):
    while True:
        try:
            return client.chat.completions.create(
                model="gpt-4.1",
                messages=messages
            )
        except Exception:
            time.sleep(1)  # Sabit gecikme, backoff yok, her şeyi yakalar

Sorunlar: exponential backoff (üstel geri çekilme) yok, yeniden denenemez hataları yakalıyor, maksimum deneme sınırı yok, jitter (rastgele gecikme) yok.

Doğru Yöntem

import time
import random
from openai import RateLimitError, APIError, APIConnectionError

def call_with_retry(messages, model="gpt-4.1", max_retries=3):
    """Exponential backoff ve jitter ile yeniden dene."""
    for attempt in range(max_retries + 1):
        try:
            return client.chat.completions.create(
                model=model,
                messages=messages
            )
        except RateLimitError as e:
            if attempt == max_retries:
                raise
            # Varsa yanıttaki retry_after değerini kullan
            wait = getattr(e, 'retry_after', None)
            if wait is None:
                wait = (2 ** attempt) + random.uniform(0, 1)
            print(f"Hız sınırına takıldı. Bekleniyor {wait:.1f}s (deneme {attempt + 1})")
            time.sleep(wait)
        except APIConnectionError:
            if attempt == max_retries:
                raise
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(wait)
        except APIError as e:
            # İstemci hatalarını (400, 401, 403) tekrar deneme
            if e.status_code and 400 <= e.status_code < 500:
                raise
            if attempt == max_retries:
                raise
            time.sleep((2 ** attempt) + random.uniform(0, 1))

Temel prensipler:

  • Exponential backoff: 1s, 2s, 4s, 8s
  • Jitter: "Thundering herd" (yığılma) problemini önlemek için eklenen rastgele 0-1s
  • Sağlandığında retry_after header'ına uyun
  • İstemci hatalarını (hatalı istek, yetkilendirme hatası) tekrar denemeyin
  • Maksimum yeniden deneme sayısı belirleyin

İki ek üretim (production) kuralı önemlidir:

  • Bir streaming endpoint'te asla sonsuza kadar yeniden deneme yapmayın
  • İşlem idempotent (aynı işlemin tekrarlanması sonucu değiştirmemesi) değilse, kullanıcı tarafından görülebilir yan etkileri olan bir isteği asla yeniden denemeyin

Chat completion'ları genellikle yeniden denemek için güvenlidir. Tool-triggered (araç tetiklemeli) yan etkiler ise genellikle değildir.

Async Versiyon

import asyncio
import random
from openai import AsyncOpenAI, RateLimitError

async_client = AsyncOpenAI(
    api_key="sk-lemon-xxx",
    base_url="https://api.lemondata.cc/v1"
)

async def call_with_retry_async(messages, model="gpt-4.1", max_retries=3):
    for attempt in range(max_retries + 1):
        try:
            return await async_client.chat.completions.create(
                model=model,
                messages=messages
            )
        except RateLimitError:
            if attempt == max_retries:
                raise
            wait = (2 ** attempt) + random.uniform(0, 1)
            await asyncio.sleep(wait)

Trafiği Bir Yeniden Deneme Fırtınasına Dönüşmeden Önce Şekillendirin

Yeniden deneme mantığı çözümün sadece yarısıdır. Kaynağınız zaten aşırı yüklendiyse, yeniden denemeler bir anlık yüklenmeyi kendi kendine neden olunan bir kesintiye dönüştürebilir.

Üç kontrol fark yaratır:

1. Kiracıya (tenant) veya kullanıcıya göre kuyruğa alma

Bir müşteri devasa bir batch (toplu) iş başlatırsa, diğer her müşterinin bundan etkilenmesini istemezsiniz.

2. Eşzamanlı akışları (concurrent streams) sınırlandırma

Streaming endpoint'leri küçümsemek kolaydır çünkü her istek açık kaldığı süre boyunca ucuz "görünür".

3. Prompt'ları ağa gitmeden önce kırpın

Token sınırları genellikle gerçek tavan sınırıdır. İki kat daha uzun bir prompt, güvenli throughput kapasitesini kabaca yarıya indirir.

İstemci Tarafı Token Bucket

Yüksek throughput'lu uygulamalar için, sunucu sınırlarına çarpmamak adına istemci tarafı hız sınırlaması uygulayın:

import time
import asyncio

class TokenBucket:
    def __init__(self, rate: float, capacity: int):
        self.rate = rate          # saniye başına token
        self.capacity = capacity  # maksimum burst boyutu
        self.tokens = capacity
        self.last_refill = time.monotonic()

    async def acquire(self, tokens: int = 1):
        while True:
            now = time.monotonic()
            elapsed = now - self.last_refill
            self.tokens = min(
                self.capacity,
                self.tokens + elapsed * self.rate
            )
            self.last_refill = now

            if self.tokens >= tokens:
                self.tokens -= tokens
                return
            # Yeterli token için bekle
            wait = (tokens - self.tokens) / self.rate
            await asyncio.sleep(wait)

# Dakikada 500 istek = saniyede ~8.3
limiter = TokenBucket(rate=8.0, capacity=20)

async def rate_limited_call(messages, model="gpt-4.1"):
    await limiter.acquire()
    return await async_client.chat.completions.create(
        model=model,
        messages=messages
    )

Token bucket'lar, tavan sınırınızı bildiğinizde iyidir. Sabit bir tahmin yerine gözlemlenen header verilerinden ayarlandıklarında ise daha da iyidirler.

Hız Sınırlarında Model Fallback (Yedekleme)

Birincil modeliniz hız sınırına takıldığında, bir alternatife geçiş yapın:

FALLBACK_CHAIN = [
    "claude-sonnet-4-6",
    "gpt-4.1",
    "gpt-4.1-mini",
]

async def call_with_fallback(messages):
    for model in FALLBACK_CHAIN:
        try:
            return await async_client.chat.completions.create(
                model=model,
                messages=messages
            )
        except RateLimitError:
            continue
    raise Exception("Tüm modeller hız sınırına takıldı")

Model gateway'lerinin yardımcı olduğu nokta burasıdır, ancak fallback'in bilinçli olması gerekir. Kullanıcı etkisini düşünmeden premium bir akıl yürütme modelinden küçük bir bütçe modeline sessizce atlamayın.

Makul bir fallback zinciri şöyledir:

  • aynı sağlayıcı, daha küçük kardeş model
  • başka bir sağlayıcıdan eşdeğer model ailesi
  • ancak o zaman daha ucuz veya daha düşük context'li bir model

Eğer "kullanılabilirlik için fallback" ile "maliyet için fallback"i tek bir adımda karıştırırsanız, hata ayıklama (debugging) hızla karmaşıklaşır.

Hız Sınırı Kullanımını İzleme

Kullanıcıları etkilemeden önce sorunları yakalamak için hız sınırı tüketiminizi takip edin:

import logging

def log_rate_limits(response):
    headers = response.headers
    remaining = headers.get("x-ratelimit-remaining-requests")
    limit = headers.get("x-ratelimit-limit-requests")
    if remaining and int(remaining) < int(limit) * 0.1:
        logging.warning(
            f"Hız sınırı uyarısı: {remaining}/{limit} istek kaldı"
        )

Kalan kapasite %10'un altına düştüğünde uyarılar ayarlayın. Bu, kullanıcılar 429 hataları görmeden önce throttling (daraltma) uygulamanız için size zaman kazandırır.

Ayrıca şunları da loglamalısınız:

  • istek ID'si (request ID)
  • model
  • giriş boyutu tahmini
  • akış (stream) süresi
  • yeniden deneme sayısı
  • nihai sonuç (success, rate_limited, network_error, quota_exhausted)

Bu alanlar olmadan, hız sınırı olayları sadece bir tahminden ibaret kalır.

Basit Bir Üretim (Production) Kontrol Listesi

Chatbot'unuzu veya agent'ınızı "hız sınırı güvenli" olarak adlandırmadan önce şu beş maddeyi doğrulayın:

  1. Hem senkron hem de asenkron yollar için sınırlı bir yeniden deneme politikası mevcut.
  2. Başarılı yanıtlarda hız sınırı header'larını logluyorsunuz.
  3. Üst kaynak çağrısından önce kullanıcı başına veya kiracı başına şekillendirme mevcut.
  4. En az bir doğrulanmış fallback modeli mevcut.
  5. Frontend, takılı kalmış bir akış yerine temiz bir hata durumu alıyor.

Sadece yeniden deneme ilkelini değil, tüm uygulamayı oluşturuyorsanız, one-key chatbot guide (tek anahtarlı chatbot kılavuzu) bu parçaların gerçek bir FastAPI servisine nasıl oturduğunu gösterir.

Özet

Hız sınırlama (rate limiting) istisnai bir durum değildir. Gerçek kullanımı olan herhangi bir AI ürünü için normal bir çalışma koşuludur. Bunu iyi yöneten ekiplerin sihirli bir şekilde daha yüksek sınırları yoktur. Onlar throughput, yeniden denemeler ve fallback'i en baştan uygulama tasarımının bir parçası olarak ele alırlar.

LemonData'da bir API anahtarı oluşturun, üretim trafiğinden önce yeniden deneme yolunuzu test edin ve bir sonraki 429 hatası gelmeden önce hazırlığınızı yapın.

Strateji Ne Zaman Kullanılır?
Exponential backoff Her zaman (temel)
İstemci tarafı hız sınırlayıcı Yüksek throughput'lu uygulamalar (>100 RPM)
Model fallback SLA gereksinimleri olan üretim uygulamaları
Proaktif izleme Herhangi bir üretim dağıtımı
Batch API Gerçek zamanlı olmayan iş yükleri

Amaç hız sınırlarından tamamen kaçınmak değildir. Onları zarif bir şekilde yönetmektir, böylece kullanıcılarınız bunu asla fark etmez.


Dayanıklı AI uygulamaları oluşturun: lemondata.cc, kaynak hız sınırlarını otomatik olarak yöneten çok kanallı yönlendirme sağlar. Tek API anahtarı, 300'den fazla model.

Share: