I’ve been watching your videos and checking out the Adocasts GitHub repo. I’m curious, when is it better to use a rate limiter inside an action or service, and when should it be applied at the route level?
For example, in Adocasts you use this code for the signup route and apply the rate limiter at the router level
export const throttleSignUp = limiter.define('signUp', (ctx) => { const ip = GetIpAddress.run(ctx.request) return limiter .allowRequests(3) .every('1 hour') .blockFor('6 hours') .usingKey(`sign_up_ip_${ip}`) .limitExceeded((error) => error.setMessage("You've created too many accounts. Please wait before creating another.") )})
For most things, applying the limiter at the route level with an HTTP limiter will likely suffice. Moving the limiter into the controller, service, or action is ideal when you need to:
Do something specific when a user is rate limited. For example, maybe you want to gracefully handle the response if you don't want the user to lose form state.
Do something before applying the rate limiter. For example, you might use a rate limit to restrict invalid login attempts to prevent someone from trying to brute force the login. In order to know whether a user should be penalized you first need to know if the provided credentials were invalid.
Since HTTP limiters are run before the controller, by moving the limiter into the controller flow you're granted more control over how and when the limiter is applied and also how the response is handled. If you don't need that added control, then using HTTP limiters at the route level is ideal for its simplicity.