Eine API ohne Ratenlimit funktioniert hervorragend – bis zu dem Moment, in dem ein Client eine Schleife ohne jede Pause schreibt. Dann verbraucht ein einzelner Aufrufer die Kapazität, die alle teilen, die Latenz steigt für jeden anderen Nutzer, und der Fehler sieht nach einem Ausfall aus statt nach einem einzigen entgleisten Skript. Ein Ratenlimit ist der Mechanismus, der dieses Szenario in einen kleinen, eingegrenzten, klar benannten Fehler für einen Client verwandelt.
Limits richtig zu setzen heißt vor allem, explizit zu sein: zu entscheiden, was du zählst, über welchen Zeitraum, pro wem, und was du einem Client sagst, der darüber hinausgeht. Dieser Leitfaden behandelt die Algorithmen, die Wahl belastbarer Zahlen, die Header, mit denen ein gut geschriebener Client innerhalb deiner Limits bleibt, und das richtige Zurückfahren, wenn du selbst der Client bist.
Warum Ratenbegrenzung wichtig ist
Limits werden meist nach einem Vorfall eingeführt, lösen aber vier getrennte Probleme gleichzeitig:
- Kapazitätsschutz. Dein Dienst hat einen maximal haltbaren Durchsatz. Ein Limit hält die Nachfrage darunter – per Entwurf, nicht per Glück.
- Fairness. Ohne Limit pro Client bekommt der lauteste Aufrufer die meisten Ressourcen. Mit Limit erhält jeder Client einen planbaren Anteil.
- Kostenkontrolle. Wenn jede Anfrage eine Datenbankabfrage, einen Fremdaufruf oder einen Modellaufruf auslöst, ist eine unbegrenzte API eine unbegrenzte Rechnung.
- Missbrauchsresistenz. Credential Stuffing, Scraping und Enumeration leben alle vom Volumen. Ein Limit macht sie langsam genug, um unpraktisch zu sein, und sichtbar genug, um Alarm zu schlagen.
Es gibt einen fünften, leiseren Vorteil: ein dokumentiertes Limit ist ein Vertrag. Clients können so gebaut werden, dass sie es respektieren – viel besser, als deine Obergrenze durch Anstoßen zu entdecken.
Die Algorithmen, die man kennen sollte
Jeder Limiter beantwortet dieselbe Frage – ist diese Anfrage jetzt erlaubt? – aber sie unterscheiden sich darin, wie sie Bursts behandeln, und genau diesen Unterschied spürt man als Client.
| Algorithmus | Erlaubt Bursts? | Am besten für |
|---|---|---|
| Token Bucket | Ja, bis zur Eimergröße | Öffentliche APIs; die übliche Wahl |
| Leaky Bucket | Nein, der Ausgang ist völlig glatt | Schutz eines Backends mit fester Kapazität |
| Festes Fenster | Ja, aber an den Grenzen unfair | Einfache Quoten, wenn Präzision kaum zählt |
| Gleitendes Fenster | Nur innerhalb des echten Limits | Exakte Durchsetzung; mehr Zustand nötig |
Token Bucket
Stell dir einen Eimer vor, der eine feste Zahl Tokens hält und sich mit konstanter Rate nachfüllt. Jede Anfrage nimmt ein Token. Ist der Eimer leer, wird die Anfrage abgelehnt. Zwei Zahlen beschreiben ihn vollständig: die Nachfüllrate, also dein dauerhafter Durchsatz, und die Eimergröße, also der größte Burst, den du zulässt.
Ein Eimer mit 100 Tokens, der 10 pro Sekunde nachfüllt, lässt einen untätigen Client sofort 100 Anfragen abfeuern und bringt ihn dann auf 10 pro Sekunde. Das ist meist genau richtig: echte Clients sind stoßweise, eine kurze Spitze ist also normaler Verkehr und kein Missbrauch, während der Langzeitdurchschnitt begrenzt bleibt. Token Bucket ist aus gutem Grund die Standardwahl – günstig zu implementieren, braucht nur Tokenzahl und Zeitstempel pro Client, und sein Verhalten lässt sich in der Dokumentation leicht erklären.
Leaky Bucket
Der Leaky Bucket ist das Spiegelbild. Anfragen kommen in eine Warteschlange und verlassen sie mit konstanter Rate, wie Wasser durch ein Loch. Ist die Schlange voll, werden neue Anfragen abgelehnt. Der Ausgang ist völlig glatt – genau das, was du vor einem Backend brauchst, das überhaupt keine Spitzen verkraftet, etwa ein Altsystem oder eine fremde API, die du weiterverkaufst.
Der Preis ist Latenz. Eine Anfrage, die in eine recht volle Schlange kommt, wartet statt schnell zu scheitern, und ein Client kann einen langsamen Server nicht von einer eingereihten Anfrage unterscheiden. Nutze ihn, um Verkehr für etwas Fragiles zu formen; nimm Token Bucket, wenn du deinen eigenen elastischen Dienst schützt.
Feste und gleitende Fenster
Ein festes Fenster zählt Anfragen pro Kalenderzeitraum: 1.000 pro Stunde, Reset zur vollen Stunde. Mit einem Zähler und einem Schlüssel trivial umzusetzen – und mit einem bekannten Fehler: dem Grenz-Burst. Ein Client, der 1.000 Anfragen um 10:59:59 und weitere 1.000 um 11:00:01 sendet, bleibt in der Richtlinie und liefert dennoch 2.000 Anfragen in zwei Sekunden – doppelt so viel wie die geplante Spitze.
Ein gleitendes Fenster behebt das, indem es über den zurückliegenden Zeitraum statt über den aktuellen Kalenderblock zählt. Um 11:00:01 sieht es die Anfragen von 10:59:59 noch und lehnt den Überschuss ab. Die exakte Variante speichert einen Zeitstempel pro Anfrage, was Speicher kostet; ein verbreiteter Kompromiss gewichtet den Zählerstand des vorigen Fensters danach, wie viel davon noch überlappt – für fast jede API genau genug, mit einem Bruchteil des Zustands.
Deine Limits wählen
Wähle Zahlen aus Messungen, nicht aus einer runden Zahl, die großzügig aussieht. Eine Reihenfolge, die funktioniert:
- Miss deine Obergrenze. Lasttest, bis die Latenz einbricht. Dieser Durchsatz, minus Reserve, ist deine echte Kapazität.
- Teile durch die erwarteten gleichzeitigen Clients. Das ist der Startpunkt für ein Limit pro Client, nicht die Endantwort.
- Schau auf deinen aktuellen Verkehr. Finde das 95. und 99. Perzentil der Anfragerate pro Client. Ein Limit unter dem 99. Perzentil weckt dich wegen echter Nutzer.
- Gib Burst-Spielraum. Etwa 10- bis 20-fach der Rate pro Sekunde ist eine verbreitete Eimergröße; sie fängt normale Seitenaufrufe ab, ohne dauerhaften Missbrauch zu erlauben.
- Staffel es. Anonyme, authentifizierte und zahlende Clients sollten kein Limit teilen. Für eine höhere Obergrenze mehr zu verlangen ist zudem der saubersten Weg, eine API zu bepreisen.
- Beobachte, bevor du durchsetzt. Protokolliere eine Woche lang, was abgelehnt worden wäre, bevor du es ablehnst.
Worauf du schlüsselst, zählt so viel wie die Zahl. Pro IP ist die einzige Option für anonymen Verkehr, bestraft aber geteilte Netze und NAT; pro API-Schlüssel ist fair und die richtige Standardwahl für authentifizierte Aufrufe; pro Konto verhindert, dass ein Client sich mit neuen Schlüsseln Kapazität kauft. Viele APIs setzen alle drei gleichzeitig ein, als globales Limit, Limit pro Schlüssel und Limit pro Endpunkt auf den teuren Routen.
Hast du eine Zahl, lässt sich die Rechnung, die daraus einen Anfrageabstand macht, leicht knapp verfehlen. Der Ratenlimit-Rechner wandelt Limit und Fenster in den minimalen Abstand zwischen Anfragen, die sichere Dauerrate und einen veröffentlichbaren Retry-After-Wert um.
Die Header, die Clients brauchen
Ein Limit, das ein Client nicht sehen kann, ist ein Limit, an das er stößt. Sende deinen Zustand bei jeder Antwort, nicht nur bei Ablehnungen:
RateLimit-Limit– die Obergrenze des aktuellen Fensters.RateLimit-Remaining– wie viele Anfragen darin noch übrig sind.RateLimit-Reset– wann das Guthaben sich erneuert, in Sekunden von jetzt.Retry-After– bei einem429oder503, wie lange zu warten ist. Entweder Sekunden oder ein HTTP-Datum.
Die Schreibweisen mit X-RateLimit-* sind weiterhin verbreitet und völlig brauchbar; die Namen ohne Präfix oben sind die standardisierte Form, und beide während einer Umstellung zu senden kostet nichts. Wichtig ist, dass die Werte vorhanden und korrekt sind, denn sie erlauben einem guten Client, sein Tempo zu halten und nie ein 429 zu sehen.
Wenn du ablehnst, gib 429 Too Many Requests zurück, nie 403 und nie ein generisches 500. Das 429 ist der einzige Code, der einem Client sagt, die Anfrage war in Ordnung und wird später gelingen – das einzige Signal, das korrektes Wiederholen hervorbringt. Unsere Referenz der HTTP-Statuscodes behandelt die verwandten Codes und was jeder einem Client abverlangt.
Ein 429 als Client behandeln
Von der anderen Seite der Verbindung sind die Regeln kurz und fast immer unzureichend umgesetzt:
- Beachte
Retry-After. Sagt dir der Server, wie lange du warten sollst, warte genau so lange. Nichts anderes ist besser informiert. - Sonst fahre exponentiell zurück. Warte 1 s, 2 s, 4 s, 8 s, bis zu einer Obergrenze. Sofort zu wiederholen macht aus einer Überlast einen selbstverschuldeten Ansturm.
- Füge Jitter hinzu. Variiere jede Wartezeit zufällig um einige hundert Millisekunden. Ohne das wiederholen alle Clients, die gemeinsam gescheitert sind, gemeinsam, und dein Backoff-Plan reproduziert die Spitze, die er verteilen sollte.
- Begrenze die Versuche. Drei bis fünf Wiederholungen, dann den Fehler melden. Unendliche Versuche verbergen einen echten Ausfall.
- Halte dein Tempo nach den Headern. Lies
RateLimit-Remainingund werde langsamer, bevor du abgelehnt wirst. Das ist der Unterschied zwischen einem Client, der funktioniert, und einem, der meistens funktioniert. - Wiederhole nie ein
4xxaußer429. Ein400oder422scheitert jedes Mal gleich, denn das Problem ist die Anfrage selbst.
Häufige Fehler, die du vermeiden solltest
403statt429zurückgeben. Clients lesen403als endgültig und hören auf, oder wiederholen blind; keines der beiden Verhalten willst du.Retry-Afterauslassen. Du hast den Client zum Raten aufgefordert, und die übliche Vermutung ist „sofort“.- Nur nach IP begrenzen. Ein ganzes Büro hinter einer NAT-Adresse wird ein Client, ein verteilter Scraper tausend.
- Alle Endpunkte gleich zählen. Ein Lesezugriff aus dem Cache und ein Bericht, der acht Sekunden rechnet, sollten nicht je ein Token kosten; gewichte teure Routen oder gib ihnen ein eigenes Limit.
- Ein festes Fenster mit knappem Limit. Der Grenz-Burst bedeutet, dass deine echte Spitze doppelt so hoch ist wie die veröffentlichte Zahl.
- Gar kein Burst-Spielraum. Ein völlig glattes Limit lehnt normalen Verkehr ab, denn echte Clients kommen in Klumpen.
- Undokumentierte Limits. Steht die Zahl nicht in deiner Dokumentation und in deinen Headern, entdeckt sie jeder Integrator in der Produktion.
- Wiederholen ohne Jitter. Synchronisierte Wiederholungen sind der Weg, auf dem eine kurze Spitze zu einer dauerhaften wird.
Berechne deine eigenen Limits
Ein gutes Ratenlimit ist langweilig: Clients halten ihr Tempo nach deinen Headern, Bursts werden abgefangen, Missbrauch wird gebremst, und niemand merkt etwas. Dorthin zu kommen ist vor allem Rechnen und Ehrlichkeit über deine echte Kapazität. Starte mit einem Limit und einem Fenster, das du wirklich halten kannst, rechne es in den Abstand und den Retry-After-Wert um, den deine Clients brauchen, veröffentliche beides und protokolliere Beinahe-Treffer, damit du ein zu knappes Limit von einem entgleisten Client unterscheiden kannst.
Verwandte Tools und Leitfäden:
- Ratenlimit-Rechner – macht aus Limit und Fenster Abstände, Burstgrößen und
Retry-After. - HTTP-Statuscodes – was
429,503und die übrigen einem Client abverlangen. - HTTP-Statuscodes: der komplette Leitfaden – alle Antwortklassen erklärt.
- DNS-Abfrage – prüfe, welchen Host dein API-Verkehr wirklich erreicht.
Häufige Fragen
Welches Ratenlimit ist ein guter Standard für eine öffentliche API?⌄
Es gibt keine allgemeingültige Zahl, denn sie hängt davon ab, was dich eine Anfrage kostet. Ein verbreiteter Startpunkt für eine leseintensive JSON-API sind 1.000 Anfragen pro Stunde und Schlüssel mit einem Burst von 20 bis 60, danach anhand eigener Perzentile nachjustieren. Miss deinen haltbaren Durchsatz, teile durch die erwarteten gleichzeitigen Clients und halte das Limit über dem 99. Perzentil des legitimen Verkehrs, damit dich keine echten Nutzer wecken.
Was ist der Unterschied zwischen Token Bucket und Leaky Bucket?⌄
Token Bucket erlaubt Bursts bis zur Eimergröße und geht dann auf die Nachfüllrate zurück, was öffentlichen APIs entspricht, weil echte Clients in Klumpen kommen. Leaky Bucket reiht Anfragen ein und gibt sie mit konstanter Rate frei, der Ausgang ist also völlig glatt, aber Anfragen warten statt schnell zu scheitern. Nimm Leaky Bucket vor einem Backend, das keine Spitze verkraftet, und Token Bucket für alles andere.
Warum ist ein festes Fenster ein Problem?⌄
Wegen des Grenz-Bursts. Ein Client, der sein ganzes Guthaben am Ende eines Fensters und sein ganzes Guthaben am Anfang des nächsten verbraucht, liefert in wenigen Sekunden doppelt so viel wie die geplante Spitze und bleibt dabei technisch in der Richtlinie. Ein gleitendes Fenster zählt über den zurückliegenden Zeitraum, dieses Muster wird also korrekt abgelehnt.
Welchen Statuscode soll ein Ratenlimiter zurückgeben?⌄
429 Too Many Requests, mit einem Retry-After-Header. Es ist der einzige Code, der einem Client sagt, die Anfrage war gültig und wird später gelingen, und genau das erzeugt korrektes Wiederholen. Ein 403 liest sich als endgültig und ein 500 als Serverfehler, beide führen Clients zu schlechtem Verhalten.
Wie soll mein Client ein 429 behandeln?⌄
Beachte Retry-After, wenn er vorhanden ist. Fehlt er, fahre exponentiell zurück – 1 s, 2 s, 4 s, 8 s – mit zufälligem Jitter auf jeder Wartezeit, damit Clients, die gemeinsam gescheitert sind, nicht gemeinsam wiederholen. Begrenze die Versuche auf drei bis fünf und melde dann den Fehler. Besser noch: lies RateLimit-Remaining bei jeder Antwort und werde langsamer, bevor du abgelehnt wirst.
Soll ich nach IP-Adresse oder nach API-Schlüssel begrenzen?⌄
Nach API-Schlüssel für authentifizierten Verkehr: das ist fair, übersteht Netzwechsel und erlaubt Staffelungen. Die IP ist die einzige Option für anonyme Anfragen, behandelt aber ein ganzes Büro hinter einer NAT-Adresse als einen Client und einen verteilten Scraper als viele. Die meisten gereiften APIs setzen beides ein, dazu ein strengeres Limit pro Endpunkt auf teuren Routen.
Über 15 Jahre praktische Erfahrung in Webentwicklung und Sicherheit. Schwerpunkt ist praxisnahe Websicherheit: Websites sicher, zuverlässig und leicht zu diagnostizieren halten. BuildToolForge macht diese Prüfungen kostenlos, privat und verständlich. Die Tools laufen, wo immer möglich, in deinem Browser, und nichts, was du in ein Tool eingibst, wird gespeichert.
So schreiben wir unsere Anleitungen: Jede Anleitung entsteht aus praktischer Erfahrung, wird mit den offiziellen Standards abgeglichen und mit unseren eigenen Tools an echten Domains getestet. Wir aktualisieren die Anleitungen, wenn sich Standards oder Tools ändern. Einen Fehler gefunden? Schreib uns an contact@buildtoolforge.com.