Comparación de dos enfoques de throttling con scope en DRF: ScopedRateThrottle vs herencia de UserRateThrottle
En DRF, al aplicar throttling basado en scope, suelen surgir dos patrones comunes.
- Enfoque A: Heredar de
UserRateThrottle(oSimpleRateThrottle) y crear una clase personalizada con scope fijado, luego asignarla directamente athrottle_classesde la vista. - Enfoque B: Registrar
ScopedRateThrottleenDEFAULT_THROTTLE_CLASSESy en la vista solo indicarthrottle_scope = "login".
Para responder a la pregunta “¿son esencialmente iguales?”:
Si el objetivo es limitar la velocidad por userID (o IP no autenticada) + scope, los resultados son casi idénticos. La diferencia radica en la forma de aplicación (prevención de errores, extensibilidad, estructura de código) y, por tanto, en la elección del patrón.
Puntos en común: ambos crean la clave con “scope + (user id o IP)”
ScopedRateThrottleconstruye la clave con scope + userID/IP cuando la vista tienethrottle_scope, y busca la tasa correspondiente enDEFAULT_THROTTLE_RATES.UserRateThrottletambién limita por user id para usuarios autenticados y por IP para no autenticados; para usar varias tasas, DRF sugiere heredar la clase y cambiar el scope.
Diferencia 1) ¿Dónde colocar el scope?: atributo de la vista vs atributo de la clase
Enfoque A: scope fijo en la clase (explícito)
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]
- El scope está fijado en la clase.
- La vista solo declara que usará esa clase.
- Se reducen los errores de tipeo en el scope, ya que el nombre de la clase actúa como documentación.
Enfoque B: scope en la vista, throttling común (centrado en la configuración)
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"
- El scope se coloca directamente en la vista.
- El
ScopedRateThrottlecomún interpreta que la vista pertenece al scope y aplica la tasa desde la configuración. - El código es más corto y la política se gestiona en un solo lugar.
Diferencia 2) ¿Quién garantiza la aplicación?: registro por defecto vs equipamiento por vista
Puntos clave del Enfoque B (mucha confusión)
Incluso si ScopedRateThrottle está en DEFAULT_THROTTLE_CLASSES, no se aplica a vistas sin throttle_scope. No hay riesgo de bloquear toda la API al registrar globalmente.
Ventaja del Enfoque A
Se puede equipar un throttle específico a una vista sin tocar la configuración global, útil cuando el entorno no permite cambios masivos o cuando solo ciertos endpoints deben ser restringidos.
Diferencia 3) Escalabilidad: cuando se supera el “un solo límite” el Enfoque A gana ventaja
La similitud se mantiene hasta “una vista, un scope, una tasa”. Más allá, las diferencias se hacen evidentes.
1) Aplicar múltiples throttles (burst + sustained) a una vista
DRF muestra un patrón con varias UserRateThrottle:
class Burst(UserRateThrottle):
scope = "burst"
class Sustained(UserRateThrottle):
scope = "sustained"
class SearchView(APIView):
throttle_classes = [Burst, Sustained]
Con ScopedRateThrottle solo, es difícil expresar “dos scopes en una vista”; se necesita una clase adicional o una implementación personalizada.
2) Cambiar el criterio de limitación
ScopedRateThrottle se basa en user id / IP. En la práctica surgen necesidades como:
- IP + nombre de usuario para proteger contra ataques dirigidos a cuentas.
- tenant_id para limitar por organización.
- API key para limitar por clave.
Estas situaciones requieren sobrescribir get_cache_key() y, por tanto, heredar y personalizar (Enfoque A). DRF también recomienda crear throttles personalizados en estos casos.

¿Cuál elegir?
Para la mayoría de los “rate limits por vista” → Enfoque B (ScopedRateThrottle)
- Código mínimo.
- Política gestionada en
settings. - Solo se aplica a vistas con
throttle_scope.
Si se cumple al menos una de las siguientes condiciones → Enfoque A (herencia/Clase personalizada)
- Se necesitan múltiples límites (burst + sustained) en la misma vista.
- El criterio de limitación no es user/IP sino algo personalizado (usuario+IP, tenant, API key, etc.).
- Se desea evitar cambios globales y equipar throttles solo a vistas específicas.
- Se quiere que el nombre de la clase sirva como documentación de la política.
Artículo relacionado: