KI-API-Rate-Limiting: Wie es funktioniert und wie man damit umgeht
Jede KI-API hat Rate Limits. Diese während der Entwicklung zu erreichen ist lästig. In der Produktion führen sie zu Fehlern für Ihre Nutzer. Zu verstehen, wie Rate Limits bei verschiedenen Anbietern funktionieren und eine passende Retry-Logik zu implementieren, ist der Unterschied zwischen einer Demo und einer produktiven Anwendung.
Wie jeder Anbieter Sie limitiert
OpenAI
OpenAI verwendet gestaffelte Rate Limits basierend auf der Nutzungshistorie und dem Zahlungslevel Ihres Kontos.
| Stufe | RPM (Anfragen/Min) | TPM (Tokens/Min) | Wie man sie erreicht |
|---|---|---|---|
| Free | 3 | 40.000 | Neues Konto |
| Tier 1 | 500 | 200.000 | $5 bezahlt |
| Tier 2 | 5.000 | 2.000.000 | $50 bezahlt |
| Tier 3 | 5.000 | 10.000.000 | $100 bezahlt |
| Tier 4 | 10.000 | 50.000.000 | $250 bezahlt |
| Tier 5 | 10.000 | 300.000.000 | $1.000 bezahlt |
Limits gelten pro Modell. Die Nutzung von GPT-4.1 verbraucht nicht Ihr Kontingent für GPT-4.1-mini.
Anthropic
Anthropic verwendet ein ähnliches Stufensystem mit Limits für RPM und TPM. Außerdem gibt es auf niedrigeren Stufen ein tägliches Token-Limit.
Google (Gemini)
Google AI Studio hat pro Modell Limits. Die kostenlose Stufe ist bei täglichen Anfragen großzügig, aber bei Anfragen pro Minute streng (15 RPM für Gemini 2.5 Free Tier).
Aggregator-Plattformen
Aggregator-Plattformen wie LemonData und OpenRouter legen eine eigene Rate-Limiting-Schicht über die Limits der Anbieter. LemonData verwendet rollenbasierte Limits:
| Rolle | RPM |
|---|---|
| User | 1.000 |
| Partner | 3.000 |
| VIP | 10.000 |
Der Vorteil: Aggregator-Limits sind meist höher als die Free-Tiers einzelner Anbieter, und Multi-Channel-Routing bedeutet, dass bei Rate-Limiting eines Upstream-Kanals die Anfrage über einen anderen Kanal geleitet wird.
Rate Limit Header auslesen
Alle großen Anbieter geben Rate-Limit-Informationen in den Antwort-Headern zurück:
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
Nutzen Sie diese Header proaktiv. Warten Sie nicht auf einen 429-Fehler, um langsamer zu werden.
Retry-Logik aufbauen
Der falsche Weg
# Nicht so machen
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) # Feste Verzögerung, kein Backoff, fängt alles ab
Probleme: kein exponentielles Backoff, fängt nicht wiederholbare Fehler ab, keine maximale Anzahl an Versuchen, kein Jitter.
Der richtige Weg
import time
import random
from openai import RateLimitError, APIError, APIConnectionError
def call_with_retry(messages, model="gpt-4.1", max_retries=3):
"""Retry mit exponentiellem Backoff und Jitter."""
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
# Verwende retry_after aus der Antwort, falls vorhanden
wait = getattr(e, 'retry_after', None)
if wait is None:
wait = (2 ** attempt) + random.uniform(0, 1)
print(f"Rate limit erreicht. Warte {wait:.1f}s (Versuch {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:
# Keine Wiederholung bei Client-Fehlern (400, 401, 403)
if e.status_code and 400 <= e.status_code < 500:
raise
if attempt == max_retries:
raise
time.sleep((2 ** attempt) + random.uniform(0, 1))
Wichtige Prinzipien:
- Exponentielles Backoff: 1s, 2s, 4s, 8s
- Jitter: zufällige 0-1s Verzögerung zur Vermeidung von Thundering-Herd
- Respektiere den
retry_after-Header, wenn vorhanden - Keine Wiederholungen bei Client-Fehlern (Bad Request, Authentifizierungsfehler)
- Setze eine maximale Anzahl an Wiederholungen
Async-Version
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)
Fortgeschritten: Token Bucket Rate Limiter
Für Anwendungen mit hohem Durchsatz implementieren Sie clientseitiges Rate Limiting, um Server-Limits zu vermeiden:
import time
import asyncio
class TokenBucket:
def __init__(self, rate: float, capacity: int):
self.rate = rate # Tokens pro Sekunde
self.capacity = capacity # Maximale Burst-Größe
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
# Warte auf genügend Tokens
wait = (tokens - self.tokens) / self.rate
await asyncio.sleep(wait)
# 500 Anfragen pro Minute = ~8,3 pro Sekunde
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
)
Modell-Fallback bei Rate Limits
Wenn Ihr primäres Modell rate-limitiert ist, greifen Sie auf ein alternatives Modell zurück:
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("Alle Modelle sind rate-limitiert")
Hier zeigen API-Aggregatoren ihre Stärke. Mit über 300 Modellen hinter einem Endpunkt haben Sie immer eine Fallback-Option.
Monitoring des Rate Limit Verbrauchs
Verfolgen Sie Ihren Verbrauch der Rate Limits, um Probleme zu erkennen, bevor sie Nutzer beeinträchtigen:
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"Rate Limit Warnung: {remaining}/{limit} Anfragen verbleibend"
)
Setzen Sie Alarme, wenn die verbleibende Kapazität unter 10 % fällt. So haben Sie Zeit, Drosselungen einzuführen, bevor Nutzer 429-Fehler sehen.
Zusammenfassung
| Strategie | Wann anwenden |
|---|---|
| Exponentielles Backoff | Immer (Grundlage) |
| Client-seitiger Rate Limiter | Apps mit hohem Durchsatz (>100 RPM) |
| Modell-Fallback | Produktions-Apps mit SLA-Anforderungen |
| Proaktives Monitoring | Jede Produktionsumgebung |
| Batch-API | Nicht-Echtzeit-Workloads |
Das Ziel ist nicht, Rate Limits komplett zu vermeiden, sondern sie so zu handhaben, dass Ihre Nutzer sie nie bemerken.
Erstellen Sie widerstandsfähige KI-Anwendungen: lemondata.cc bietet Multi-Channel-Routing, das Upstream-Rate-Limits automatisch handhabt. Ein API-Schlüssel, 300+ Modelle.
