Easy Rails controller rate limiting with Rails.cache

Here's an easy trick I reach for when wanting to add simple rate limiting to an endpoint.

def special_endpoint
  model = Model.find(params[:id])
  cache_key = "rate_limit:mymodel:#{model.id}"

  # If the key exists, we rate limit
  if Rails.cache.fetch(cache_key)
    return render json: { code: "too_many_requests", message: "Test webhooks can only be sent once every 20 seconds." }, status: :too_many_requests

  # do something expensive here

  # Set the key to block operations for 20 seconds
  Rails.cache.write(cache_key, true, expires_in: 20.seconds)

This makes use of Rails.cache to store a key for 20 seconds. If the method is hit again while the key exists, we return an error. Otherwise we allow the operation to complete.

This is a quick and easy way to add a simple rate limit to a controller. For more advanced scenarios I typically use Rack Attack.