Kurzfassung
Rate Limiting ist die Begrenzung der Anzahl von API-Anfragen in einer bestimmten Zeit. Es schützt vor Missbrauch, DDoS und gewährleistet fairen Ressourcenzugriff. So implementieren Sie Rate Limiting 2026.
Für wen ist das
- Entwickler, die öffentliche APIs bauen
- Teams, die Schutz vor Missbrauch brauchen
- Unternehmen, die API als Produkt anbieten
- Projekte, die Kostenkontrolle erfordern
Keyword (SEO)
rate limiting, api rate limit, ddos protection, api security, throttling, express rate limit, redis rate limiting
Was ist Rate Limiting?
Rate Limiting ist:
- Begrenzung der Anzahl von Anfragen in der Zeit
- Schutz vor Missbrauch und DDoS
- Fairen Zugriff auf Ressourcen
- Kostenkontrolle für Infrastruktur
Beispiel:
Limit: 100 Anfragen pro Minute
Benutzer 1: 50 Anfragen ✅
Benutzer 2: 150 Anfragen ❌ (nach 100 blockiert)
Warum Rate Limiting?
1. Schutz vor Missbrauch
Szenarien:
- Bot-Scraping von Daten
- Brute-Force-Angriffe
- API-Missbrauch
- Unbefugter Zugriff
Ohne Rate Limiting:
Angreifer: 10.000 Anfragen/Sekunde
Server: Überlastet, Absturz
Mit Rate Limiting:
Angreifer: 10.000 Anfragen/Sekunde
Rate Limiter: Blockiert nach 100/Min
Server: Funktioniert normal
2. Kostenkontrolle
Problem:
- Jede Anfrage kostet (Compute, Datenbank)
- Unbegrenzte API = unbegrenzte Kosten
- Schwere Budgetkontrolle
Lösung:
- Limits pro Benutzer
- Ressourcennutzungskontrolle
- Vorhersehbare Kosten
3. Fairen Zugriff
Für alle Benutzer:
- Ein Benutzer kann API nicht monopolisieren
- Gleicher Ressourcenzugriff
- Besseres Erlebnis
4. Fehlervermeidung
Schutz vor:
- Versehentlicher Endlosschleife
- Fehlern im Client-Code
- Unsachgemäßer API-Nutzung
Rate Limiting Strategien
1. Fixed Window
Wie es funktioniert:
- Zeitfenster (z. B. 1 Minute)
- Zähler setzt sich jedes Fenster zurück
- Einfach zu implementieren
Beispiel:
Fenster: 1 Minute
Limit: 100 Anfragen
00:00-00:59: 100 Anfragen ✅
01:00-01:59: Zurücksetzen, neue 100 Anfragen ✅
Problem:
- Burst an Fenstergrenzen
- Möglichkeit von 200 Anfragen in 2 Sekunden (am Ende und Anfang des Fensters)
2. Sliding Window
Wie es funktioniert:
- Fenster, das sich in der Zeit verschiebt
- Zählt Anfragen aus letzten N Sekunden
- Fairer
Beispiel:
Limit: 100 Anfragen pro 60 Sekunden
00:00: 50 Anfragen (verfügbar: 50)
00:30: 30 Anfragen (verfügbar: 20)
01:00: 20 Anfragen (verfügbar: 0, blockiert)
01:30: Anfragen von 00:30 laufen ab (verfügbar: 20)
3. Token Bucket
Wie es funktioniert:
- Eimer mit Token
- Token werden in konstanter Rate hinzugefügt
- Anfrage verbraucht Token
- Keine Token = blockiert
Beispiel:
Kapazität: 100 Token
Hinzufügen: 10 Token/Sekunde
Anfrage: 1 Token
4. Leaky Bucket
Wie es funktioniert:
- Eimer mit Loch
- Anfragen gehen in Eimer
- Konstante Leckrate
- Volles Eimer = blockiert
Implementierung
1. Express.js mit express-rate-limit
Installation:
npm install express-rate-limit
Grundlegende Verwendung:
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 Minuten
max: 100, // 100 Anfragen pro Fenster
message: 'Zu viele Anfragen, bitte später erneut versuchen.',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
Verschiedene Limits für verschiedene Endpunkte:
// Allgemeines Limit
const generalLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
});
// Strengeres Limit für Auth
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // Nur 5 Login-Versuche
skipSuccessfulRequests: true,
});
app.use('/api/', generalLimiter);
app.use('/api/auth/login', authLimiter);
Mit Redis (für mehrere Instanzen):
npm install express-rate-limit redis
import RedisStore from 'rate-limit-redis';
import { createClient } from 'redis';
const redisClient = createClient();
await redisClient.connect();
const limiter = rateLimit({
store: new RedisStore({
client: redisClient,
prefix: 'rl:',
}),
windowMs: 15 * 60 * 1000,
max: 100,
});
2. Next.js API Routes
Middleware-Ansatz:
// lib/rateLimit.ts
import { NextRequest, NextResponse } from 'next/server';
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
const redis = new Redis({
url: process.env.UPSTASH_REDIS_REST_URL!,
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
});
const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(10, '10 s'),
});
export async function rateLimit(request: NextRequest) {
const ip = request.ip ?? '127.0.0.1';
const { success, limit, remaining } = await ratelimit.limit(ip);
if (!success) {
return NextResponse.json(
{ error: 'Zu viele Anfragen' },
{ status: 429 }
);
}
return { limit, remaining };
}
Verwendung in API Route:
// app/api/users/route.ts
import { rateLimit } from '@/lib/rateLimit';
export async function GET(request: NextRequest) {
const rateLimitResult = await rateLimit(request);
if (rateLimitResult instanceof NextResponse) {
return rateLimitResult; // Rate Limit überschritten
}
// Normale Logik
return NextResponse.json({ users: [] });
}
3. Custom Implementierung mit Redis
Sliding Window Log:
import { createClient } from 'redis';
const redis = createClient();
await redis.connect();
async function checkRateLimit(
key: string,
limit: number,
windowSeconds: number
): Promise<{ allowed: boolean; remaining: number }> {
const now = Date.now();
const windowStart = now - windowSeconds * 1000;
// Alte Anfragen entfernen
await redis.zRemRangeByScore(key, 0, windowStart);
// Aktuelle Anfragen zählen
const count = await redis.zCard(key);
if (count >= limit) {
return { allowed: false, remaining: 0 };
}
// Neue Anfrage hinzufügen
await redis.zAdd(key, {
score: now,
value: `${now}-${Math.random()}`,
});
// TTL setzen
await redis.expire(key, windowSeconds);
return { allowed: true, remaining: limit - count - 1 };
}
// Verwendung
const result = await checkRateLimit('user:123', 100, 60);
if (!result.allowed) {
return res.status(429).json({ error: 'Rate Limit überschritten' });
}
Best Practices
1. Verschiedene Limits für verschiedene Endpunkte
Strategie:
const limits = {
public: { windowMs: 15 * 60 * 1000, max: 100 },
auth: { windowMs: 15 * 60 * 1000, max: 5 },
upload: { windowMs: 60 * 60 * 1000, max: 10 },
search: { windowMs: 60 * 1000, max: 20 },
};
2. Benutzeridentifikation
Methoden:
- IP-Adresse (für öffentliche APIs)
- API-Key (für autorisierte)
- Benutzer-ID (für eingeloggte)
- Session-ID
Beispiel:
function getIdentifier(req: Request): string {
// Priorität: API-Key > Benutzer-ID > IP
return (
req.headers.get('x-api-key') ||
req.user?.id ||
req.ip ||
'anonymous'
);
}
3. Informative Header
Standard-Header:
res.setHeader('X-RateLimit-Limit', '100');
res.setHeader('X-RateLimit-Remaining', '50');
res.setHeader('X-RateLimit-Reset', resetTime);
4. Graceful Degradation
Statt vollständig blockieren:
if (rateLimitExceeded) {
// Option 1: Anfrage in Warteschlange
await queueRequest(request);
// Option 2: Drosseln (verlangsamen)
await sleep(1000);
// Option 3: Gecachte Daten zurückgeben
return getCachedResponse();
}
5. Monitoring und Alerts
Verfolgen:
- Anzahl blockierter Anfragen
- Top Benutzer/IPs
- Missbrauchsmuster
- Performance-Auswirkungen
Rate Limiting vs Throttling
| Rate Limiting | Throttling |
|---|---|
| Blockiert nach Limit | Verlangsamt Anfragen |
| Hard Limit | Soft Limit |
| 429 Status | Verzögert Antwort |
| Für Sicherheit | Für Performance |
FAQ
Welche Limits setzen?
Hängt vom Fall ab:
- Öffentliche API: 100-1000/Min
- Auth-Endpunkte: 5-10/Min
- Upload: 10-50/Stunde
- Suche: 20-100/Min
Was tun, wenn Limit überschritten?
- 429 Status zurückgeben
- Retry-After Header hinzufügen
- Benutzer informieren
- Upgrade-Plan anbieten
Verlangsamt Rate Limiting API?
Minimal (meist <1ms). Lohnend, Redis für Cache und schnelles Prüfen zu verwenden.
Wie Rate Limiting testen?
// Test
for (let i = 0; i < 150; i++) {
const res = await fetch('/api/endpoint');
if (i >= 100) {
expect(res.status).toBe(429);
}
}