Instance Public methods
rate_limit(to:, within:, by: -> { request.remote_ip } Link
Applies a rate limit to all actions or those specified by the normal before_action filters with only: and except:.
The maximum number of requests allowed is specified by to: and constrained to the window of time given by within:.
Both to: and within: can be static values, callables, or method names (as symbols) that will be evaluated in the context of the controller processing the request.
Rate limits are by default unique to the ip address making the request, but you can provide your own identity function by passing a callable in the by: parameter. It’s evaluated within the context of the controller processing the request.
By default, rate limits are scoped to the controller’s path. If you want to share rate limits across multiple controllers, you can provide your own scope, by passing value in the scope: parameter.
Requests that exceed the rate limit will raise an ActionController::TooManyRequests error. By default, Action Dispatch will rescue from the error and refuse the request with a 429 Too Many Requests response. You can specialize this by passing a callable in the with: parameter. It’s evaluated within the context of the controller processing the request.
Rate limiting relies on a backing ActiveSupport::Cache store and defaults to config.action_controller.cache_store, which itself defaults to the global config.cache_store. If you don’t want to store rate limits in the same datastore as your general caches, you can pass a custom store in the store parameter.
If you want to use multiple rate limits per controller, you need to give each of them an explicit name via the name: option.
Examples:
class SessionsController < ApplicationController rate_limit to: 10, within: 3.minutes, only: :create end class SignupsController < ApplicationController rate_limit to: 1000, within: 10.seconds, by: -> { request.domain }, with: :redirect_to_busy, only: :new private def redirect_to_busy redirect_to busy_controller_url, alert: "Too many signups on domain!" end end class APIController < ApplicationController RATE_LIMIT_STORE = ActiveSupport::Cache::RedisCacheStore.new(url: ENV["REDIS_URL"]) rate_limit to: 10, within: 3.minutes, store: RATE_LIMIT_STORE rate_limit to: 100, within: 5.minutes, scope: :api_global rate_limit to: :max_requests, within: :time_window, by: -> { current_user.id } private def max_requests current_user.premium? ? 1000 : 100 end def time_window current_user.premium? ? 1.hour : 1.minute end end class SessionsController < ApplicationController rate_limit to: 3, within: 2.seconds, name: "short-term" rate_limit to: 10, within: 5.minutes, name: "long-term" end
# File actionpack/lib/action_controller/metal/rate_limiting.rb, line 80 def rate_limit(to:, within:, by: -> { request.remote_ip }, with: -> { raise TooManyRequests }, store: cache_store, name: nil, scope: nil, **options) before_action -> { rate_limiting(to: to, within: within, by: by, with: with, store: store, name: name, scope: scope || controller_path) }, **options end