Skip to content

Rate-Limiting — Wie Prilog 3.000 Schulen gleichzeitig bedient

Warum das wichtig ist

Prilog ist eine zentrale Plattform: eine einzige API (api.prilog.chat) bedient alle Schulen, Kitas und Einrichtungen gleichzeitig. Jede Einrichtung — ob 15 Eltern oder 200 Lehrkraefte — teilt sich dieselbe Infrastruktur.

Das funktioniert nur, wenn kein einzelner Tenant die Plattform fuer alle anderen lahmlegen kann. Ob durch einen Software-Bug, einen falsch konfigurierten Automatisierungs-Workflow oder einen gezielten Angriff — die anderen 2.999 Schulen muessen davon nichts merken.

Genau das stellt das Rate-Limiting sicher. Es ist kein technisches Detail, sondern eine Verfuegbarkeits-Garantie.


Das Problem ohne Rate-Limiting

Stellen Sie sich vor: Eine Schule hat einen Automatisierungs-Workflow (n8n), der durch einen Konfigurationsfehler in einer Endlosschleife landet. Der Workflow schickt 50.000 API-Requests pro Minute. Ohne Rate-Limiting passiert Folgendes:

  1. Die API wird ueberlastet — Response-Zeiten steigen von 50ms auf 10 Sekunden
  2. Alle 3.000 Schulen spueren das: der Chat laed nicht, Krankmeldungen gehen nicht durch, der Morgen-Check haengt
  3. Bis ein Administrator das Problem bemerkt und manuell eingreift, koennte eine Stunde vergehen
  4. In dieser Stunde ist die gesamte Plattform fuer 3.000 Einrichtungen unbenutzbar

Mit Rate-Limiting: Der fehlerhafte Workflow wird nach 2.000 Requests (Light-Plan) automatisch gebremst und nach dem Limit blockiert. Die Schule bekommt eine Fehlermeldung. Alle anderen 2.999 Schulen merken nichts.


5-Schichten-Architektur

Prilog schuetzt die Plattform mit fuenf aufeinander aufbauenden Schichten. Jede Schicht faengt eine andere Art von Problem ab. Wenn eine Schicht versagt, greift die naechste.

Internet (Angreifer, Bots, DDoS)

┌───────┴─────────────────────────────────────────────┐
│ Schicht 1: Edge-Schutz (Bunny.net)                  │
│                                                      │
│ Was: Verdaechtige IPs werden blockiert bevor sie     │
│      unsere Server ueberhaupt erreichen.             │
│                                                      │
│ Schuetzt vor: DDoS-Angriffe, bekannte Bot-Netze,    │
│ automatisierte Scans, Geographie-basierte Angriffe   │
│                                                      │
│ Wie: DNS-basiertes Filtering, IP-Reputation,         │
│ TLS-Terminierung, Challenge-Pages bei Verdacht       │
└───────┬─────────────────────────────────────────────┘
        │ Nur legitimer Traffic kommt durch
┌───────┴─────────────────────────────────────────────┐
│ Schicht 2: Nginx Rate-Limit (pro Server)            │
│                                                      │
│ Was: Grobe IP-basierte Limits, bevor ein Request     │
│      ueberhaupt die Anwendung (Node.js) erreicht.   │
│                                                      │
│ Schuetzt vor: Einzelne IPs die massiv Requests       │
│ senden (Brute-Force Login, API-Scraping)             │
│                                                      │
│ Wie: 30 Requests/Sekunde pro IP, Login-Endpoints     │
│ strenger (5/Sekunde). Gepuffert, nicht hart.         │
└───────┬─────────────────────────────────────────────┘
        │ Nur normale Request-Raten kommen durch
┌───────┴─────────────────────────────────────────────┐
│ Schicht 3: Redis Sliding Window (pro Tenant)        │
│                                                      │
│ Was: Jede Einrichtung hat ein eigenes Budget.        │
│      Alle Mitarbeitenden und Eltern einer Schule     │
│      teilen sich dieses Budget.                      │
│                                                      │
│ Schuetzt vor: Ein Tenant verbraucht                  │
│ ueberproportional viele Ressourcen.                  │
│                                                      │
│ Wie: Redis Sorted Sets mit Sliding Window.           │
│ Ueberlebt Server-Restarts. Skaliert horizontal.      │
│                                                      │
│ Limits nach Plan:                                    │
│   Light (Kita/kleine Schule): 2.000 Req/Minute      │
│   Pro (grosse Schule):       10.000 Req/Minute       │
│   Dedicated (eigener Server): 20.000 Req/Minute      │
└───────┬─────────────────────────────────────────────┘

┌───────┴─────────────────────────────────────────────┐
│ Schicht 4: Graceful Degradation                     │
│                                                      │
│ Was: Statt hart abzuschneiden (0 auf 100 in einem   │
│      Request), wird der Tenant sanft abgebremst.     │
│                                                      │
│ Schuetzt vor: Schlechte User-Experience. Ein         │
│ ploetzliches "429 Too Many Requests" verwirrt.       │
│ Stattdessen wird es einfach langsamer.               │
│                                                      │
│ Wie:                                                 │
│   0-80%  des Budgets: volle Geschwindigkeit          │
│   80-99% des Budgets: kuenstliche Verzoegerung       │
│          (linear, max 2 Sekunden)                    │
│   100%: HTTP 429 + Retry-After Header                │
│                                                      │
│ Der Effekt: Wenn ein Workflow zu schnell laeuft,     │
│ wird er automatisch langsamer — oft loest sich das   │
│ Problem von selbst, ohne dass jemand eingreifen muss.│
└───────┬─────────────────────────────────────────────┘

┌───────┴─────────────────────────────────────────────┐
│ Schicht 5: Monitoring + Alerting                    │
│                                                      │
│ Was: Echtzeit-Uebersicht welcher Tenant wie viel     │
│      verbraucht. Automatische Benachrichtigung bei   │
│      Dauerlast.                                      │
│                                                      │
│ Schuetzt vor: Unbemerkte Probleme. Wenn ein Tenant   │
│ 10 Minuten lang ueber 80% liegt, stimmt etwas       │
│ nicht — der Admin wird per Mail informiert.           │
│                                                      │
│ Wie:                                                 │
│   - Dashboard: Top-10 Verbraucher, Auslastung in %  │
│   - Auto-Alert: Mail bei 80%+ ueber 10 Minuten      │
│   - API: GET /admin/rate-limits                      │
└─────────────────────────────────────────────────────┘

Warum 5 Schichten und nicht eine?

Jede Schicht hat einen anderen Blickwinkel:

SchichtSiehtReagiert auf
1. EdgeIP-AdressenDDoS, Bots, Geographie
2. NginxIP + URLBrute-Force, Scraping
3. RedisTenant-IdentitaetUeberverbrauch, Bug-Loops
4. DegradationAuslastungs-LevelSanftes Abbremsen statt Crash
5. MonitoringLangzeit-TrendsDauerlast, schleichende Probleme

Wenn nur eine Schicht existiert (z.B. nur Nginx), dann:

  • Ein Tenant mit 200 Usern an 200 verschiedenen IPs umgeht das IP-Limit problemlos
  • Ein DDoS mit einer IP wird zwar geblockt, aber erst nachdem er Node.js erreicht hat
  • Niemand bemerkt, dass ein Tenant seit Stunden am Limit operiert

Zusammen bilden die 5 Schichten ein lueckenloses Netz.


Fail-Open statt Fail-Closed

Eine wichtige Design-Entscheidung: Wenn Redis ausfaellt (Netzwerk-Problem, Redis-Restart), wird der Request durchgelassen, nicht blockiert.

Warum? Das Rate-Limiting schuetzt vor Missbrauch. Wenn es selbst ausfaellt, ist die Plattform fuer ein paar Minuten ungeschuetzt — das ist besser als die Plattform fuer alle zu blockieren weil der Rate-Limiter kaputt ist.

Das ist ein bewusstes Trade-Off:

  • Fail-Closed (Request blockieren wenn Rate-Limiter kaputt): Sicherer, aber ein Redis-Ausfall bedeutet kompletter Plattform-Ausfall
  • Fail-Open (Request durchlassen): Weniger sicher fuer wenige Minuten, aber die Plattform laeuft weiter

Fuer eine Schul-Plattform ist Verfuegbarkeit wichtiger als perfekte Rate-Limitierung.


Technische Details

Sliding Window Algorithmus

Anders als ein festes Zeitfenster ("maximal 5000 Requests pro Minute ab :00") nutzt Prilog ein Sliding Window (gleitendes Fenster). Das verhindert die sogenannte "Burst-at-Boundary"-Luecke:

Festes Fenster (schlecht):

Minute 1 (:00-:59): 4999 Requests (knapp unter Limit)
Minute 2 (:00-:59): 5000 Requests
→ In den 2 Sekunden um den Minutenwechsel: 9999 Requests!

Sliding Window (gut):

Jeder Request schaut 60 Sekunden zurueck.
Egal wann: es sind nie mehr als 5000 in den letzten 60 Sekunden.

Die Implementierung nutzt Redis Sorted Sets:

  • Jeder Request wird als Eintrag mit Timestamp gespeichert
  • Bei jeder Pruefung werden Eintraege aelter als 60 Sekunden entfernt
  • Die Anzahl der verbleibenden Eintraege ist die aktuelle Nutzung
  • Alles in einer atomaren Redis-Pipeline (MULTI/EXEC)

Per-Plan Limits

PlanRequests/MinuteTypischer Tenant
Light2.000Kita, kleine Schule (≤20 User)
Pro10.000Grosse Schule (20-500 User)
Dedicated20.000Eigener Server (unbegrenzt User)

Die Limits sind grosszuegig bemessen. Zum Vergleich: ein normaler Schulbetrieb mit 200 Usern erzeugt etwa 500-800 Requests pro Minute. Das Pro-Limit von 10.000 bietet also >10x Headroom.

Response-Headers

Jeder API-Response enthaelt Rate-Limit-Informationen:

X-RateLimit-Limit: 10000          ← Maximales Budget
X-RateLimit-Remaining: 9247       ← Verbleibendes Budget
X-RateLimit-Slowdown: 150         ← Kuenstliche Verzoegerung (ms), nur bei >80%
Retry-After: 12                   ← Sekunden bis naechster Versuch (nur bei 429)

Gut implementierte Clients (Automatisierungen, Integrationen) koennen diese Headers auswerten und ihr Verhalten anpassen.


Was passiert wenn das Limit erreicht wird?

Fuer Endnutzer (Web-Client)

Nichts Sichtbares. Das Web-Client-Budget reicht fuer normalen Betrieb immer aus. Nur wenn eine Automatisierung im Hintergrund laeuft und das Budget aufbraucht, koennte es zu leichten Verzoegerungen kommen (Schicht 4: Graceful Degradation).

Fuer Automatisierungen (n8n)

Workflows die zu schnell laufen, werden automatisch langsamer (Schicht 4). Wenn das Limit erreicht ist, gibt die API HTTP 429 zurueck. Gut geschriebene n8n-Workflows respektieren den Retry-After-Header und warten.

Fuer den Admin

Der Admin sieht im Health-Dashboard:

  • Welcher Tenant wie viel verbraucht
  • Ob jemand dauerhaft ueber 80% liegt
  • Automatische Mail-Benachrichtigung bei Dauerlast

Vergleich mit anderen Plattformen

PlattformRate-LimitingAnsatz
Google WorkspacePer-User + Per-OrganisationSliding Window, 429 + Retry-After
Microsoft 365Per-TenantFixed Window, 429 + Retry-After
Slack APIPer-Token + Per-WorkspaceSliding Window, Tier-basiert
PrilogPer-Tenant + Per-PlanSliding Window, Graceful Degradation

Prilog's Ansatz ist vergleichbar mit dem was Google und Slack nutzen — Sliding Window ist der Industriestandard fuer faire Lastverteilung.


Zusammenfassung

Rate-Limiting ist keine technische Spielerei, sondern eine Grundvoraussetzung fuer den Betrieb einer Multi-Tenant-Plattform. Es garantiert:

  1. Verfuegbarkeit: Ein Problem bei einer Schule betrifft nie alle anderen
  2. Fairness: Jede Schule bekommt ihren fairen Anteil an Ressourcen
  3. Sicherheit: Angriffe werden in 5 Schichten abgefangen
  4. Transparenz: Admins sehen in Echtzeit wer wie viel verbraucht
  5. Sanfte Behandlung: Statt harter Ablehnung wird zuerst gebremst

Die Architektur skaliert von 10 bis 10.000 Tenants ohne Aenderung.