u/BothZookeepergame285

▲ 2 r/django

How I protected my Django REST API with custom throttling — login was wide open to brute force

I was building a Django REST API with JWT auth and realized

my login endpoint had zero rate limiting. Anyone could

attempt logins as fast as their connection allowed.

DRF's default throttling puts the same rate on every

endpoint. That makes no sense — your public feed endpoint

and your login endpoint are completely different threat

surfaces.

Here's the fix I used — custom throttle classes per endpoint:

from rest_framework.throttling import AnonRateThrottle

class LoginThrottle(AnonRateThrottle):

rate = '5/minute'

scope = 'login'

class OTPThrottle(AnonRateThrottle):

rate = '3/minute'

scope = 'otp'

class PasswordResetThrottle(AnonRateThrottle):

rate = '5/hour'

scope = 'password_reset'

Then apply per view:

class LoginView(APIView):

throttle_classes = [LoginThrottle]

def throttled(self, request, wait):

raise Throttled(detail={

"message": "Too many attempts. Please wait.",

"wait_seconds": int(wait)

})

The wait_seconds in the error response is important —

your frontend can show a real countdown instead of a

generic error message.

Three things I learned:

  1. 5/minute on login is more than enough for real users

  2. Always test throttling with pytest — loop requests

    until you hit 429 to confirm it's actually working

  3. If you run multiple servers, use Redis as your cache

    backend or throttling won't work across instances

I wrote the full breakdown with pytest examples and

Redis setup here:

https://learnpython-xi.vercel.app/post/0c469fda-d843-4d87-9ca1-0a606387d84e

Happy to answer questions — been running this in

production for a few weeks now.

reddit.com
u/BothZookeepergame285 — 2 days ago