EMZETT.
Login

Rate Limiting

Kurz: Eine Technik, um zu begrenzen, wie oft ein Nutzer/eine IP-Adresse in einem Zeitraum Anfragen stellen darf — schützt vor Missbrauch (z. B. Brute-Force-Logins, Spam) und Überlastung.

Genauer: Häufig über einen schnellen Zwischenspeicher wie Redis umgesetzt (ein Zähler pro Nutzer/IP mit Ablaufzeit). Wird das Rate-Limiting auf JEDEN Request angewendet (auch harmlose Lese-Seiten), kostet das bei jedem Seitenaufruf einen zusätzlichen Netzwerk-Roundtrip — spürbar in der Ladezeit.

Kontext bei uns: Lief bei Emzett zunächst global auf jedem Request, wurde dann auf reine GET/HEAD-Lese-Seiten ohne Formulare eingeschränkt (Login, Checkout, Chat, Admin bleiben weiterhin voll geschützt), um Ladezeit und Redis-Last zu sparen.

Im Detail

Das gängigste Rate-Limiting-Verfahren ist das “Sliding Window”: Statt einfach zu zählen “wie viele Requests seit der letzten vollen Minute”, wird ein gleitendes Zeitfenster betrachtet (z. B. “wie viele Requests in den letzten 60 Sekunden, ab jetzt gerechnet”) — das verhindert, dass jemand kurz vor und kurz nach einer Minutengrenze jeweils das volle Limit ausnutzt und dadurch effektiv doppelt so viele Requests wie erlaubt durchbekommt. Bibliotheken wie @upstash/ratelimit implementieren das serverlos über Redis, ohne dass man selbst Zeitfenster-Logik schreiben muss:

const ratelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(100, "1 m"), // 100 Requests pro Minute
});
 
const { success } = await ratelimit.limit(`edge:${ip}`);
if (!success) {
  return new Response("Zu viele Anfragen", { status: 429 });
}

Wichtig ist, WELCHER Identifikator zum Zählen benutzt wird: reine IP-Adresse ist einfach, aber problematisch hinter gemeinsam genutzten NATs/Firmennetzwerken (viele echte Nutzer teilen sich eine sichtbare IP) und leicht umgehbar über IP-Rotation; eine Kombination aus IP + Nutzerkonto (wo verfügbar) ist präziser. Bei global verteilten Edge-Umgebungen (wie Vercel Edge Functions) muss der Zähler-Speicher selbst ebenfalls global konsistent sein — ein lokaler In-Memory-Zähler pro Server-Instanz würde bei mehreren parallel laufenden Instanzen das Limit faktisch vervielfachen, weshalb ein zentraler Store wie Redis nötig ist.

Siehe auch: Upstash Redis