DRF Throttling: Scope gebruiken – Vergelijking tussen ScopedRateThrottle en UserRateThrottle‑subclass

In DRF komen twee veelvoorkomende patronen voor bij scope‑gebaseerde throttling.

  • Patroon A: Maak een eigen klasse door UserRateThrottle (of SimpleRateThrottle) te erven, stel een scope in en koppel deze direct aan de view via throttle_classes.
  • Patroon B: Registreer ScopedRateThrottle in DEFAULT_THROTTLE_CLASSES en geef in de view alleen throttle_scope = "login".

Vraag: "Is het uiteindelijk hetzelfde?"

Voor een enkel rate‑limiet gebaseerd op ‘userID (of niet‑geauthenticeerde IP) + scope’ zijn de resultaten vrijwel identiek. Verschillen ontstaan in de manier van toepassen (foutpreventie), uitbreidbaarheid (meerdere policies/aanpassingen) en de code‑structuur (configuratie‑gericht vs code‑gericht).


1. Gemeenschappelijke basis: Beide gebruiken “scope + (userID of IP)” als sleutel

  • ScopedRateThrottle bouwt de sleutel uit scope + userID/IP wanneer throttle_scope aanwezig is, en zoekt de bijbehorende rate in DEFAULT_THROTTLE_RATES.
  • UserRateThrottle beperkt standaard op userID voor geauthenticeerde gebruikers en op IP voor niet‑geauthenticeerde. Voor meerdere scopes wordt aanbevolen een subclass te maken.

2. Verschil 1: Waar wordt de scope gedefinieerd? – View‑attribuut vs Class‑attribuut

Patroon A: Scope vast in de klasse (expliciet)

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]
  • De scope is vast in de klasse.
  • De view hoeft alleen aan te geven dat deze klasse gebruikt wordt.
  • Minder kans op typfouten in de scope‑string; de klasse fungeert als documentatie.

Patroon B: Scope in de view, gedeelde throttle (configuratie‑gericht)

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"
  • De scope staat direct in de view.
  • De gedeelde throttle (ScopedRateThrottle) bepaalt of het een login‑scope is en haalt de rate uit de settings.
  • Code is korter en policies zijn centraal beheerd.

3. Verschil 2: Wie garandeert de toepassing? – Standaardregistratie vs View‑specifieke installatie

Patroon B: Veel misvattingen

Het toevoegen van ScopedRateThrottle aan DEFAULT_THROTTLE_CLASSES heeft geen effect op views zonder throttle_scope. Dus je hoeft je geen zorgen te maken dat alle API‑punten ineens geblokkeerd worden.

Patroon A: Sterke punten

Je kunt zonder globale instellingen een specifieke view een throttle toewijzen. Dit is handig als je de settings niet kunt aanpassen of alleen een bepaald app/endpoint wilt afdwingen.


4. Verschil 3: Schaalbaarheid – Wanneer A voordeliger wordt

De twee patronen lijken gelijk voor één scope en één rate per view. Vanaf daar divergeren ze.

1) Meerdere throttles (burst + sustained) op één view

DRF laat zien hoe je meerdere UserRateThrottle‑subclasses kunt gebruiken:

class Burst(UserRateThrottle):
    scope = "burst"

class Sustained(UserRateThrottle):
    scope = "sustained"

class SearchView(APIView):
    throttle_classes = [Burst, Sustained]

Met alleen ScopedRateThrottle is het lastig om twee scopes op één view te hanteren; je hebt een subclass nodig (of een aangepaste implementatie).

2) Veranderen van de basis voor throttling

ScopedRateThrottle werkt standaard op userID/IP. In de praktijk ontstaan vaak andere vereisten:

  • Login: limiet op IP + gebruikersnaam (tegen account‑targeting).
  • Organisatie/tenant: limiet op tenant_id.
  • API‑sleutel: limiet op de sleutel zelf.

Dit vereist een aangepaste get_cache_key()‑implementatie, wat leidt tot een subclass (Patroon A). DRF moedigt ook custom throttles aan.


Twee sleutels die een API‑verbinding openen

5. Welke aanpak kiezen?

Voor de meeste “view‑specifieke rate limits” → Patroon B (ScopedRateThrottle)

  • Minder code
  • Policies centraal in settings
  • Alleen throttle_scope in de view
  • Views zonder scope worden niet beperkt

Als een van de volgende geldt → Patroon A (subclass/aanpassing)

  • Meerdere limieten (burst + sustained) op één view
  • Een custom basis (bijv. username+IP, tenant, API‑sleutel)
  • Je kunt de globale settings niet aanpassen en wil een specifieke view afdwingen
  • Je wilt de policy documenteren via de klassenaam

Meer lezen: