Rate-Limiting ist eine Kontrolle, die deckelt, wie viele Anfragen ein Client pro Fenster stellen darf; Throttling bremst den Überschuss, statt ihn abzulehnen. Nehmen Sie den dritten Verwandten hinzu – die Quota (das Kontingent), eine Zuteilung pro Abrechnungszeitraum – und Sie haben das vollständige Vokabular, das die meisten Erklärungen zu einem einzigen Wort verschmelzen. Zusammen sorgen die drei dafür, dass APIs fair, rentabel und erreichbar bleiben.
Das Wichtigste in Kürze
| Frage | Antwort |
|---|---|
| Rate Limit | Harte Obergrenze pro kurzem Fenster – der Überschuss erhält 429 |
| Throttle | Der Überschuss wird gebremst oder eingereiht, nicht abgewiesen |
| Quota | Die Zuteilung über den langen Horizont – pro Tag/Monat, pro Tarif |
| Die Stimme des Servers | 429 + Retry-After + Rate-Limit-Header |
| Die Manieren des Clients | Retry-After respektieren; exponentielles Backoff mit Jitter |
Was die 429-Antwort und die Rate-Limit-Header bedeuten
HTTP/1.1 429 Too Many Requests ← RFC 6585
Retry-After: 30 ← so lange warten (Sekunden oder Datum)
X-RateLimit-Limit: 1000 ← Ihr Budget in diesem Fenster
X-RateLimit-Remaining: 0 ← was davon übrig ist
X-RateLimit-Reset: 1767024000 ← wann es sich auffüllt
RateLimit: "default";r=0;t=30 ← die entstehende IETF-Standardform
Die Client-Hälfte des Vertrags – der Code, den jeder SDK-Nutzer irgendwann braucht:
// JavaScript / Node.js — Back4app JS SDK
// The client half of rate limiting: back off, with jitter, then retry
async function withBackoff(fn, attempt = 0) {
try {
return await fn();
} catch (e) {
if (e.code !== 155 || attempt >= 4) throw e; // 155: request limit hit
const wait = 2 ** attempt * 500 + Math.random() * 200;
await new Promise((r) => setTimeout(r, wait)); // exponential + jitter
return withBackoff(fn, attempt + 1);
}
}
const results = await withBackoff(() => query.find()); // Flutter / Dart — Back4app Flutter SDK
// The client half of rate limiting: back off, with jitter, then retry
Future<ParseResponse> withBackoff(Future<ParseResponse> Function() fn,
[int attempt = 0]) async {
final response = await fn();
if (response.success || attempt >= 4) return response;
final wait = (1 << attempt) * 500 + Random().nextInt(200);
await Future.delayed(Duration(milliseconds: wait)); // exponential + jitter
return withBackoff(fn, attempt + 1);
}
final response = await withBackoff(() => query.query()); // iOS / Swift — Back4app Swift SDK
// The client half of rate limiting: back off, with jitter, then retry
func withBackoff<T>(_ attempt: Int = 0,
_ fn: @escaping () async throws -> T) async throws -> T {
do { return try await fn() }
catch {
guard attempt < 4 else { throw error }
let wait = pow(2.0, Double(attempt)) * 0.5 + .random(in: 0...0.2)
try await Task.sleep(for: .seconds(wait)) // exponential + jitter
return try await withBackoff(attempt + 1, fn)
}
}
let results = try await withBackoff { try await query.find() } // Android / Kotlin — Back4app Android SDK
// The client half of rate limiting: back off, with jitter, then retry
suspend fun <T> withBackoff(attempt: Int = 0, fn: suspend () -> T): T {
return try {
fn()
} catch (e: ParseException) {
if (attempt >= 4) throw e
val wait = (1L shl attempt) * 500 + Random.nextLong(200)
delay(wait) // exponential + jitter
withBackoff(attempt + 1, fn)
}
}
val results = withBackoff { query.find() } Token Bucket vs. Leaky Bucket vs. festes Fenster vs. gleitendes Fenster
| Algorithmus | Bursts | Genauigkeit | Speicher | Urteil |
|---|---|---|---|---|
| Token Bucket | Erlaubt, bis zur Bucket-Größe | Gut | Minimal | Der API-Standard – schubweise Menschen, stabiler Durchschnitt |
| Leaky Bucket | Zu gleichmäßigem Tropfen geglättet | Gut | Gering | Traffic-Shaping – konstanter Ausgang, zusätzliche Latenz |
| Festes Fenster | Burst an der Grenze: 2× Limit an den Rändern | Schwach | Minimal | Einfach und notorisch austricksbar |
| Gleitendes Fenster | Kontrolliert | Am besten | Mäßig | Der Skalierungskompromiss, bei dem die meisten Plattformen landen |
Eine verteilte Fußnote, die die Diagramme auslassen: Bei vielen API-Servern muss der Bucket an einem gemeinsamen Ort leben – typischerweise in einem In-Memory-Store, der atomare Inkremente ausführt – und Sie wählen zwischen strenger Genauigkeit (jede Prüfung geht an den Store) und Geschwindigkeit (lokale Zähler, lockere Synchronisation). Die meisten Plattformen akzeptieren leicht lockere Limits als Preis für die Latenz; vertraglich zugesicherte Quotas bekommen die strenge Behandlung.
Geltungsbereich: Wer genau wird begrenzt?
Pro IP stoppt anonyme Fluten und Sickerverluste bei der DDoS-Absorption, aber ein Büro-NAT macht aus Hunderten Benutzern eine einzige Adresse. Pro Schlüssel bindet Limits an Anwendungen und Preismodelle – der Geltungsbereich, der die eigentliche Arbeit leistet. Pro Benutzer hindert ein Konto daran, den Schlüssel einer geteilten App zu monopolisieren. Pro Endpoint bepreist teure Operationen ehrlich – Such- und Export-Endpoints verdienen engere Budgets als Health Checks. Produktivsysteme schichten sie übereinander; die zusammengesetzte Frage lautet immer: “Welches Budget hat diese Anfrage verbraucht?”
Typische Anwendungsfälle
- Schutz öffentlicher APIs – der kanonische Fall: faire Budgets pro Schlüssel, in Headern veröffentlicht, an der Grenze durchgesetzt.
- Durchsetzung von Tarifstufen – kostenlose gegenüber bezahlten Tarifen, die sich genau in Quota und Burst-Spielraum unterscheiden.
- Abwehr von Missbrauch und Scraping – enge Limits für Anonyme, großzügige für Authentifizierte.
- Kostenkontrolle auf teuren Pfaden – LLM-Aufrufe, Exporte, Suchen: Budgets pro Endpoint, die die tatsächlichen Kosten abbilden.
- Selbstverteidigung auf Client-Seite – Backoff und Zusammenfassen von Anfragen gegenüber den Limits anderer, die Ihre Integrationen respektieren müssen, um nicht gesperrt zu werden.
Ablehnen oder throtteln? Eine Entscheidungsmatrix
| Rate Limit (ablehnen), wenn… | Throttle (bremsen/einreihen), wenn… |
|---|---|
| Clients intelligent wiederholen können | Die Arbeit am Ende stattfinden muss |
| Sie interaktive Kapazität schützen | Sie Batch- und Hintergrundlast glätten |
| Der Vertrag auf Anfragen pro Fenster lautet | Der Vertrag auf Fairness des Dienstes lautet |
| Schnelle Rückmeldung mehr wiegt als später Erfolg | Später Erfolg mehr wiegt als ein Fehler |
| Der Verkehr anonym oder nicht vertrauenswürdig ist | Die Produzenten Ihre eigenen, internen sind |
Und die Meta-Regel: Was immer Sie wählen, veröffentlichen Sie es – Limits in der Dokumentation und in Headern verwandeln eine frustrierende Mauer in einen technischen Vertrag, auf dem Clients aufbauen können.
Grenzen und Trade-offs
- Limits sind grobe Werkzeuge. Eine Anfrage ist keine Kosteneinheit – ein billiger Lesezugriff und ein monströser Export verbrauchen beide “1”. Kostenbewusstes Limitieren (Punkte pro Operation) ist die Verfeinerung, zum Preis der Komplexität.
- Verteilte Genauigkeit kostet Latenz. Strenge globale Zähler serialisieren sich auf einem gemeinsamen Store; lockere lokale lassen am Rand zu viel durch. Wählen Sie nach der Garantie, nicht nach der Mode.
- 429er bestrafen die unschuldige Wiederholungsschleife. Clients ohne Jitter synchronisieren sich zu Thundering Herds; das Design Ihres Limiters muss den schlimmsten Client annehmen, denn er wird ihm begegnen.
- Throttling verbirgt Überlastung. Eingereihte Anfragen glätten die Diagramme und bauen dabei unsichtbaren Rückstau auf; Queues brauchen Obergrenzen und Verwerfungsregeln, sonst werden sie zu aufgeschobenen Ausfällen.
- Limits sind Produktentscheidungen im Ops-Gewand. Budgets, Tarifstufen und Burst-Spielräume prägen Nutzererlebnis und Umsatz – legen Sie sie mit geöffneter Preisseite fest, nicht nur mit dem Dashboard.
Rate-Limiting mit Back4app
Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Schutz ist hier eine Voreinstellung der Plattform und kein Projekt: Anfragelimits greifen an der Grenze, pro App und pro Tarif, teure Operationen lassen sich hinter Cloud-Code-Funktionen mit eigenen Prüfungen legen, und Clients erhalten saubere 429-Semantik – die das Backoff-Muster auf SDK-Seite aus den Code-Tabs oben in widerstandsfähiges Verhalten statt fehlgeschlagener Bildschirme verwandelt. Sie stellen Richtlinien ein; den Limiter bauen Sie nicht.
Häufige Fragen
Was ist API-Rate-Limiting?
Eine Kontrolle, die deckelt, wie viele Anfragen ein Client innerhalb eines Zeitfensters stellen darf – etwa tausend pro Stunde und Schlüssel. Anfragen über der Obergrenze werden abgelehnt, klassisch mit HTTP 429 Too Many Requests. Das schützt den Dienst vor Überlastung und Missbrauch, verhindert, dass ein einzelner schwergewichtiger Client alle anderen ausbremst, und macht Kapazitätsplanung überhaupt erst möglich.
Was ist der Unterschied zwischen Rate-Limiting, Throttling und Quotas?
Drei Werkzeuge, die oft zu einem einzigen Wort verschmelzen. Rate-Limiting lehnt überzählige Anfragen rundheraus ab. Throttling bremst sie stattdessen oder reiht sie ein – die Anfrage geht am Ende durch, nur später. Eine Quota ist die Zuteilung über den langen Horizont: Anfragen pro Tag oder Monat, gebunden an einen Tarif oder eine Rechnung. Kurze Fenster schützen die Infrastruktur, Quotas definieren die geschäftliche Abmachung, Throttling glättet die Kanten.
Was bedeutet Fehler 429 und wie behebe ich ihn?
Sie haben die im aktuellen Fenster erlaubten Anfragen überschritten. Die Lösung ist Disziplin auf Client-Seite: den Header Retry-After lesen, falls vorhanden, und so lange warten; sonst mit exponentiellem Backoff plus Jitter erneut versuchen. Die falsche Lösung – sofortige blinde Wiederholungsversuche – verschlimmert die Lage für Sie und für alle anderen, und genau dafür gibt es Backoff.
Wie funktioniert der Token-Bucket-Algorithmus?
Ein Bucket hält Tokens, die sich mit gleichbleibender Rate auffüllen; jede Anfrage verbraucht eines. Ein voller Bucket lässt einen Burst durch – die Bucket-Größe ist der Burst-Spielraum –, während die Auffüllrate den nachhaltigen Durchschnitt erzwingt. Diese burstfreundliche Form ist der Grund, warum Token Bucket der Standardalgorithmus für nutzernahe APIs ist.
Warum ist ein Rate Limiter mit festem Fenster problematisch?
Wegen des Bursts an der Fenstergrenze: Bei einem Limit von 100 pro Minute kann ein Client um 11:59:59 Uhr 100 Anfragen senden und um 12:00:01 Uhr weitere 100 – 200 in zwei Sekunden, und alles regelkonform. Algorithmen mit gleitendem Fenster gewichten das vorherige Fenster mit, um die Lücke zu schließen, zum Preis etwas aufwendigerer Buchführung. Das ist der klassische Grund, warum "Anfragen pro Minute" eine Definition der Minute braucht.
Welche Rate-Limit-Header gibt es?
Zuerst die Konvention: X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset nennen dem Client sein Budget, den Rest davon und den Zeitpunkt der Auffüllung – populär gemacht von großen API-Anbietern. Die Standardisierung kommt über die IETF-Header RateLimit und RateLimit-Policy. So oder so: Erst das Veröffentlichen der Limits in Headern macht aus Rate-Limiting statt einer Mauer einen Vertrag.
Was ist exponentielles Backoff mit Jitter?
Der höfliche Wiederholungsversuch: nach aufeinanderfolgenden Fehlschlägen 1 s warten, dann 2 s, 4 s, 8 s – und jeder Wartezeit einen Zufallsanteil (den Jitter) hinzufügen. Der Jitter zählt mehr, als er aussieht: Ohne ihn versuchen es alle Clients, die gemeinsam gescheitert sind, gemeinsam erneut und hämmern in synchronen Wellen auf den genesenden Dienst ein. Der Zufall bricht die Thundering Herd.
Sollten Limits pro IP, pro API-Schlüssel oder pro Benutzer gelten?
In Schichten, denn jeder Geltungsbereich versagt für sich allein: pro IP stoppt anonyme Fluten, bestraft aber Büros hinter einer einzigen Adresse; pro Schlüssel bindet Limits an Anwendungen und Tarife; pro Benutzer hindert ein Konto daran, eine geteilte App zu monopolisieren; pro Endpoint schützt gezielt teure Operationen. Produktivsysteme kombinieren meist zumindest schlüssel- und endpointbezogene Limits.