class Rack::Attack
throttle('logins/ip', limit: 5, period: 20.seconds) do |request|
request.ip if request.path == '/users/sign_in' && request.post?
end
throttle('password_reset/email', limit: 3, period: 15.minutes) do |request|
if request.path == '/password_resets' && request.post?
request.params['email'].to_s.downcase.strip
end
end
self.throttled_responder = lambda do |_env|
[429, { 'Content-Type' => 'application/json' }, [{ error: 'rate_limited' }.to_json]]
end
end
Rate limiting is both a security control and an availability control. I use it to slow credential stuffing, login brute force, and noisy scraping without punishing normal use. The trick is keying limits on the right dimensions and emitting metrics so you know whether you are actually blocking abuse.