🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

So implementieren Sie die Ratenbegrenzung in einer Node.js-API: Vollständiger Leitfaden für 2026

⏱️5 min read  ·  907 words

Ratenbegrenzung schützt Ihre API vor Missbrauch, verhindert versehentliche Überlastung und gewährleistet eine faire Nutzung über alle Clients hinweg. Ohne sie kann ein einzelner Client (oder Angreifer) Ihren Server überfordern. Dieser Leitfaden implementiert eine robuste Ratenbegrenzung in Node.js von einfach bis produktionstauglich.

Warum Ratenbegrenzung?

  • Missbrauch verhindern: Stoppen Sie Brute-Force-Angriffe und Scraping
  • Für Fairness sorgen: Kein einzelner Kunde monopolisiert Ressourcen
  • Kontrollkosten: Begrenzen Sie teure Vorgänge (KI-Aufrufe, DB-Abfragen)
  • Stabilität schützen: Verhindern Sie versehentliche oder böswillige Überlastung

Die wichtigsten Algorithmen

Algorithmus Wie es funktioniert Kompromiss
Festes Fenster N Anfragen pro festes Zeitfenster Einfach, erlaubt aber Bursts an Fensterrändern
Schiebefenster N Anfragen in den letzten X Sekunden (rollend) Sanfter, etwas komplexer
Token-Bucket Tokens füllen sich mit der Zeit wieder auf; Jede Anfrage kostet einen Ermöglicht kontrollierte Bursts, flexibel

Ganz einfach: express-rate-limit

npm install express-rate-limit
const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,   // 15 minutes
  max: 100,                    // 100 requests per window per IP
  standardHeaders: true,       // return RateLimit-* headers
  legacyHeaders: false,
  message: { error: 'Too many requests, please try again later.' },
});

// Apply globally
app.use(limiter);

// Or stricter limits on specific routes
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,   // only 5 login attempts per 15 min
});
app.post('/login', authLimiter, loginHandler);

Produktion: Redis-gestützte Ratenbegrenzung

In-Memory-Limits funktionieren nicht über mehrere Serverinstanzen hinweg. Redis teilt die Grenzwerte für alle Instanzen:

npm install rate-limit-redis ioredis
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');

const redis = new Redis(process.env.REDIS_URL);

const limiter = rateLimit({
  store: new RedisStore({
    sendCommand: (...args) => redis.call(...args),
  }),
  windowMs: 15 * 60 * 1000,
  max: 100,
});

app.use(limiter);
// Now all server instances share the same rate-limit counters

Benutzerdefinierter Token-Bucket mit Redis

async function tokenBucket(key, maxTokens, refillRate) {
  const now = Date.now();
  const bucket = await redis.hgetall(`bucket:${key}`);

  let tokens = parseFloat(bucket.tokens ?? maxTokens);
  let lastRefill = parseInt(bucket.lastRefill ?? now);

  // Refill tokens based on elapsed time
  const elapsed = (now - lastRefill) / 1000;
  tokens = Math.min(maxTokens, tokens + elapsed * refillRate);

  if (tokens < 1) {
    return { allowed: false, retryAfter: (1 - tokens) / refillRate };
  }

  tokens -= 1;  // consume one token
  await redis.hset(`bucket:${key}`, { tokens, lastRefill: now });
  await redis.expire(`bucket:${key}`, 3600);

  return { allowed: true, remaining: Math.floor(tokens) };
}

// Middleware
async function rateLimitMiddleware(req, res, next) {
  const result = await tokenBucket(req.ip, 10, 1);  // 10 tokens, 1/sec refill
  if (!result.allowed) {
    res.setHeader('Retry-After', Math.ceil(result.retryAfter));
    return res.status(429).json({ error: 'Rate limit exceeded' });
  }
  res.setHeader('X-RateLimit-Remaining', result.remaining);
  next();
}

Beschränkung pro Benutzer (nicht nur pro IP)

// Rate limit by authenticated user ID instead of IP
const userLimiter = rateLimit({
  windowMs: 60 * 1000,
  max: 60,
  keyGenerator: (req) => {
    // Use user ID if authenticated, fall back to IP
    return req.user?.id || req.ip;
  },
  store: new RedisStore({ sendCommand: (...args) => redis.call(...args) }),
});

// Tiered limits based on plan
function getLimitForUser(req) {
  const plan = req.user?.plan || 'free';
  return { free: 100, pro: 1000, enterprise: 10000 }[plan];
}

Korrekte Antwortheader festlegen

// Standard rate-limit headers help clients back off gracefully
res.setHeader('RateLimit-Limit', limit);
res.setHeader('RateLimit-Remaining', remaining);
res.setHeader('RateLimit-Reset', resetTimestamp);

// On limit exceeded, always include Retry-After
res.status(429)
   .setHeader('Retry-After', secondsUntilReset)
   .json({ error: 'Too many requests' });

Best Practices

  • Verwenden Sie Redis für Multi-Instanz-Apps – In-Memory-Grenzwerte werden nicht serverübergreifend synchronisiert
  • Strengere Grenzwerte für sensible Endpunkte — Anmeldung, Passwort-Zurücksetzung und Zahlungsendpunkte erfordern strenge Grenzwerte
  • Gibt klare Header zurück — RateLimit-* und Retry-After helfen Clients, sich gut zu verhalten
  • Ratenbegrenzung durch Benutzer bei Authentifizierung — fairer als nur IP (gemeinsam genutzte IPs, Proxys)
  • Berücksichtigen Sie abgestufte Grenzwerte — unterschiedliche Limits für kostenlose und kostenpflichtige Benutzer
  • Mit anderen Verteidigungsmaßnahmen kombinieren — Ratenbegrenzung ist eine Ebene, keine vollständige Sicherheitslösung

Häufig gestellte Fragen

F: Welchen Algorithmus soll ich verwenden?
A: Token-Bucket für Flexibilität (ermöglicht kontrollierte Bursts), Schiebefenster für mehr Glätte, festes Fenster für Einfachheit. Für die meisten APIs ist die Standardeinstellung von express-rate-limit (festes/gleitendes Fenster) in Ordnung. Der Token-Bucket eignet sich für APIs, bei denen gelegentliche Bursts akzeptabel sind.

F: Sollte ich eine Ratenbegrenzung nach IP oder Benutzer vornehmen?
A: Nach Benutzer-ID bei der Authentifizierung (fairer, verarbeitet gemeinsam genutzte IPs), bei anonymen Anfragen wird auf die IP zurückgegriffen. Eine reine IP-Beschränkung kann Benutzer hinter Shared NATs oder Unternehmens-Proxys ungerechtfertigt beeinträchtigen.

F: Warum wird mein Tariflimit unerwartet zurückgesetzt?
A: Bei der In-Memory-Begrenzung über mehrere Instanzen verfügt jeder Server über einen eigenen Zähler – ein Client, der auf verschiedene Instanzen trifft, sieht inkonsistente Grenzwerte. Verwenden Sie Redis, um den Status über alle Instanzen hinweg zu teilen.

F: Welchen Statuscode soll ich zurückgeben?
A: 429 Zu viele Anfragen mit einemRetry-After Header, der dem Client mitteilt, wie lange er warten soll. Das ist der Standard, den wohlerzogene Kunden respektieren.

F: Kann eine Ratenbegrenzung DDoS-Angriffe stoppen?
A: Es hilft gegen Missbrauch auf Anwendungsebene, ist aber kein vollständiger DDoS-Schutz. Verwenden Sie für groß angelegte Angriffe zusätzlich zur Anwendungsratenbegrenzung ein CDN/WAF (Cloudflare, AWS Shield) am Netzwerkrand.

Fazit

Die Ratenbegrenzung ist wichtig, um Ihre Node.js-API vor Missbrauch und Überlastung zu schützen. Beginnen Sie mitExpress-Ratenlimit für einfache Fälle und wechseln Sie zuRedis-gestützte Begrenzung Für Produktionsanwendungen mit mehreren Instanzen wird daher die serverübergreifende Synchronisierung eingeschränkt. Wenden Sie strengere Grenzwerte für sensible Endpunkte (Anmeldung, Zahlungen) an, begrenzen Sie die Rate pro Benutzer bei der Authentifizierung und geben Sie immer „clear “ zurück undRateLimit-* Header, damit sich die Clients ordnungsgemäß zurückziehen. Kombinieren Sie es mit einem CDN/WAF für eine umfassende Verteidigung.Retry-After Header, damit sich die Clients ordnungsgemäß zurückziehen. Kombinieren Sie es mit einem CDN/WAF für eine umfassende Verteidigung.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা