Comparaison des deux approches de throttling basé sur le scope dans DRF : ScopedRateThrottle vs héritage de UserRateThrottle
Dans DRF, deux schémas courants apparaissent lorsqu’on applique un throttling basé sur le scope.
- Approche A : hériter de
UserRateThrottle(ouSimpleRateThrottle) pour créer une classe personnalisée contenant lescope, puis l’attacher directement à la vue viathrottle_classes. - Approche B : enregistrer
ScopedRateThrottledansDEFAULT_THROTTLE_CLASSESet ne préciser quethrottle_scope = "login"dans la vue.
Pour répondre à la question « est-ce que les deux donnent le même résultat ? » :
Si l’on veut simplement limiter la vitesse par userID (ou IP non authentifié) + scope, les résultats sont quasiment identiques. La différence réside dans la façon d’appliquer (prévention d’erreurs), l’évolutivité (plusieurs politiques / critères personnalisés) et la structure du code (configuration centralisée vs code local).
Points communs : les deux créent une clé « scope + (user id ou IP) »
ScopedRateThrottleconstruit la clé en combinant lescope(s’il est présent dans la vue) avec l’ID utilisateur ou l’IP, puis applique le taux correspondant trouvé dansDEFAULT_THROTTLE_RATES.UserRateThrottlelimite également par ID utilisateur (authentifié) ou IP (non authentifié) et, pour gérer plusieurs scopes, DRF propose d’hériter de la classe et de définir unscopedifférent.
Différence 1) Où placer le scope : propriété de la vue ou de la classe
Approche A : scope fixé dans la classe (explicite)
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]
- Le
scopeest défini dans la classe. - La vue indique simplement qu’elle utilise cette classe.
- On évite les fautes de frappe dans le
scope(la classe sert de documentation).
Approche B : scope dans la vue, throttling commun (centré sur la configuration)
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"
- Le
scopeest déclaré directement dans la vue. - Le throttling commun (
ScopedRateThrottle) lit cescopeet applique le taux défini dans les settings. - Le code est plus court et la politique est gérée en un seul endroit.
Différence 2) Qui garantit l’application : enregistrement global ou montage par vue
Point clé de l’approche B (souvent mal compris)
Même si ScopedRateThrottle est dans DEFAULT_THROTTLE_CLASSES, il ne s’applique pas aux vues sans throttle_scope.
Il n’est donc pas nécessaire de craindre que l’ajout global bloque toutes les API.
Avantage de l’approche A
On peut ajouter un throttling spécifique à une vue sans toucher la configuration globale. C’est utile lorsqu’on ne peut pas modifier les settings ou lorsqu’on veut forcer une politique uniquement sur un endpoint particulier.
Différence 3) Évolutivité : l’approche A devient préférable au-delà d’une seule restriction
Les deux approches semblent identiques tant qu’on a une seule restriction par vue. Au-delà, les différences apparaissent.
1) Appliquer plusieurs throttles (burst + sustained) à une même vue
DRF montre un exemple d’utilisation de plusieurs UserRateThrottle pour gérer un burst et un sustained.
class Burst(UserRateThrottle):
scope = "burst"
class Sustained(UserRateThrottle):
scope = "sustained"
class SearchView(APIView):
throttle_classes = [Burst, Sustained]
Avec ScopedRateThrottle, il est difficile d’associer deux scopes à une même vue sans créer de classes supplémentaires.
2) Changer le critère de limitation (pas seulement user/IP)
ScopedRateThrottle se base sur l’ID utilisateur ou l’IP. En pratique, on peut vouloir limiter par :
- IP + nom d’utilisateur (pour contrer les attaques ciblées sur un compte)
tenant_id(pour les applications multi‑tenant)- Clé API (pour les clés individuelles)
Ces scénarios nécessitent de surcharger get_cache_key() ou d’utiliser une classe personnalisée, ce qui conduit naturellement à l’approche A.

Quelle approche choisir ?
Pour la plupart des cas de rate limit par vue → Approche B (ScopedRateThrottle)
- Code minimal
- Politique centralisée dans les settings
- Seule la vue avec
throttle_scopeest affectée
Si l’un des points suivants s’applique → Approche A (héritage / classe personnalisée)
- On veut appliquer plusieurs restrictions (burst + sustained) à une même vue
- Le critère de limitation n’est pas user/IP mais un critère personnalisé (username+IP, tenant, clé API, etc.)
- On ne peut pas modifier les settings globaux et on veut forcer la politique sur une vue spécifique
- On souhaite que le nom de la classe serve de documentation explicite
Article lié :