DRF Throttling: Verwendung von „scope“ – Vergleich von ScopedRateThrottle und UserRateThrottle-Vererbung
In DRF gibt es zwei häufig verwendete Muster, wenn man scope-basiertes Throttling einsetzt.
- Muster A: Eine eigene Klasse erstellen, die von
UserRateThrottle(oderSimpleRateThrottle) erbt und dort einen festen scope definiert. Diese Klasse wird dann direkt überthrottle_classesan der View verwendet. - Muster B:
ScopedRateThrottleinDEFAULT_THROTTLE_CLASSESregistrieren und in der View lediglichthrottle_scope = "login"setzen.
Die Frage „Gibt es letztlich keinen Unterschied?“ lässt sich so beantworten:
Wenn du nur ein einzelnes Rate-Limit auf Basis von „user ID (oder nicht authentifizierter IP) + scope“ brauchst, ist das Ergebnis nahezu identisch. Unterschiede zeigen sich jedoch bei Fehlkonfigurationen (Absicherung), Erweiterbarkeit (mehrere Richtlinien/benutzerdefinierte Kriterien) und der Code-Struktur (settings-zentriert vs. code-zentriert).
Gemeinsamkeit: Beide erzeugen einen Schlüssel aus „scope + (user ID oder IP)“
ScopedRateThrottlebaut den Schlüssel austhrottle_scope(falls vorhanden) plus user ID bzw. IP und sucht die passende Rate inDEFAULT_THROTTLE_RATES.UserRateThrottledrosselt ebenfalls nach user ID (authentifiziert) bzw. IP (nicht authentifiziert). Für mehrere Richtlinien empfiehlt DRF, die Klasse zu erben und unterschiedlichescope-Werte zu setzen.
Unterschied 1) Wo wird der scope definiert? – View-Attribut vs. Klassen-Attribut
Muster A: scope fest in der Klasse (explizit)
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class CustomDomainSaveThrottle(UserRateThrottle):
scope = "custom_domain_save"
class SaveCustomDomainView(APIView):
throttle_classes = [CustomDomainSaveThrottle]
- Der
scopeist in der Klasse festgelegt. - Die View muss lediglich die Klasse referenzieren.
- Tippfehler im
scope-String werden reduziert – der Klassenname dient praktisch als Dokumentation.
Muster B: scope in der View, gemeinsamer Throttle (settings-zentriert)
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": [
"rest_framework.throttling.ScopedRateThrottle",
],
"DEFAULT_THROTTLE_RATES": {
"login": "5/min",
}
}
from rest_framework.views import APIView
class LoginView(APIView):
throttle_scope = "login"
- Der
scopewird direkt in der View gesetzt. - Der gemeinsame Throttle (
ScopedRateThrottle) liestthrottle_scopeaus und holt die Rate aus den Einstellungen. - Der Code bleibt kompakt, und Richtlinien lassen sich zentral in den settings verwalten.
Unterschied 2) Wer stellt die Anwendung sicher? – Globale Registrierung vs. View-spezifisches Anhängen
Punkt zu Muster B (häufig missverstanden)
Selbst wenn ScopedRateThrottle in DEFAULT_THROTTLE_CLASSES registriert ist, greift es nicht bei Views ohne throttle_scope. Eine globale Registrierung throttelt also nicht automatisch alle Endpoints.
Vorteil von Muster A
Ohne globale Einstellungen zu verändern, kann man gezielt bestimmte Views mit dem gewünschten Throttle „ausstatten“. Das ist nützlich, wenn settings nur eingeschränkt angepasst werden dürfen oder nur einzelne Endpoints streng limitiert werden sollen.
Unterschied 3) Erweiterbarkeit: Mehr als ein einzelnes Limit – Muster A ist im Vorteil
Die beiden Muster wirken ähnlich, solange jede View genau einen scope und ein Limit hat. Sobald mehr nötig ist, werden die Unterschiede deutlich.
1) Mehrere Throttles (z. B. Burst + Sustained)
Die DRF-Dokumentation zeigt ein Muster mit mehreren UserRateThrottle-Subklassen für Burst- und Sustained-Limits.
class Burst(UserRateThrottle):
scope = "burst"
class Sustained(UserRateThrottle):
scope = "sustained"
class SearchView(APIView):
throttle_classes = [Burst, Sustained]
Mit reinem ScopedRateThrottle lässt sich nicht elegant „zwei scopes auf einer View“ ausdrücken – dafür braucht man wieder eigene Klassen (oder zusätzliche Logik).
2) Andere Kriterien als user ID/IP
ScopedRateThrottle arbeitet standardmäßig mit user ID bzw. IP. In der Praxis kommen jedoch schnell Anforderungen wie diese hinzu:
- Login: Limitierung nach IP + Benutzername (z. B. gegen account-targeted Angriffe).
- Multi-Tenant-Systeme: Limitierung nach tenant_id.
- API-Keys: Limitierung pro Schlüssel.
Diese Fälle erfordern typischerweise eine Anpassung von get_cache_key() und führen damit zu einer benutzerdefinierten Throttle-Klasse – also zu Muster A.

Was sollte man wählen?
Für die meisten „View-spezifischen Rate-Limits“ → Muster B (ScopedRateThrottle)
- Minimaler Code
- Zentrale Verwaltung über settings
- Nur Views mit
throttle_scopewerden limitiert
Wenn eines der folgenden zutrifft → Muster A (Vererbung/benutzerdefinierte Klasse)
- Mehrere Limits (z. B. Burst + Sustained) gleichzeitig auf einer View
- Kriterien jenseits von user ID/IP (z. B. IP + Benutzername, Tenant, API-Key)
- Globale Einstellungen sollen nicht verändert werden, aber bestimmte Views müssen throttled werden
- Klassenname soll als „Dokumentation“ dienen
Weiterführender Artikel:
Es sind keine Kommentare vorhanden.