> For the complete documentation index, see [llms.txt](https://docs.lightningrails.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.lightningrails.com/deploying-to-production/security/rate-limiting.md).

# Rate Limiting

Implementing Rate Limiting in Your Ruby on Rails App with rack-attack

Implement rate limiting using the rack-attack gem to enhance the security of your Rails application and prevent abuse. This gem helps throttle excessive requests and block abusive traffic efficiently.

Follow these step-by-step instructions to integrate **rack-attack** into your Lightning Rails app.

### **Step 1: Add the rack-attack Gem**

First, add the [**rack-attack** gem](https://github.com/rack/rack-attack) to your `Gemfile`:

```ruby
gem 'rack-attack'
```

Then, install the gem by running:

```sh
bundle install
```

### **Step 2: Configure rack-attack**

Now, configure the rate limiting rules by creating an initializer file:

```sh
touch config/initializers/rack_attack.rb
```

Open the file and add the following configuration:

```ruby
class Rack::Attack
  # Throttle requests from the same IP address to 5 requests per second
  throttle('req/ip', limit: 5, period: 1.second) do |req|
    req.ip
  end

  # Block IPs that fail authentication too many times
  Rack::Attack.blocklist('block bad IPs') do |req|
    Rack::Attack::Fail2Ban.filter("bad-ips", maxretry: 5, findtime: 1.minute, bantime: 5.minutes) do
      req.ip if req.path == "users/sign_in" || "users/sign_up" && req.post?
    end
  end

  # Allow whitelisted IPs to bypass rate limits
  safelist('allow from localhost') do |req|
    '127.0.0.1' == req.ip
  end

  # Log blocked requests
  ActiveSupport::Notifications.subscribe("rack.attack") do |name, start, finish, request_id, payload|
    Rails.logger.info "[Rack::Attack] Throttled: #{payload[:request].ip}" if payload[:request]
  end
end
```

This configuration:

* Limits all requests to **5 per second per IP**.
* Blocks IPs that exceed **5 failed login attempts within a minute**.
* Allows **localhost (127.0.0.1)** to bypass rate limits, you can add other IPs if needed
* Logs blocked requests for monitoring on your production server.

This last point was very usefull to me as when I suspected a bot attack, I checked the IP address and realised it was Google's IP address trying to index my site 😅

### **Step 3: Test Your Configuration**

1. **Restart Your Server**\
   Run the following command to apply the changes:

   ```sh
   shCopyEditrails restart
   ```
2. **Monitor Logs**\
   Check your Rails logs (`log/development.log`) to see if any IPs are being throttled or blocked:

   ```sh
   shCopyEdittail -f log/development.log
   ```

   If rate limits are hit, you will see messages like:

   ```
   cppCopyEdit[Rack::Attack] Throttled: 192.168.1.100
   ```
3. **Adjust Limits**
   * Modify the `limit` and `period` values to suit your needs.
   * Tweak `maxretry`, `findtime`, and `bantime` for authentication-related restrictions.
   * Add **custom rules** to protect specific endpoints like API requests.

***

### **Step 4: Deploy and Monitor**

Once tested locally, deploy your changes to production. Monitor logs and adjust limits based on real-world traffic patterns.

You can also integrate **Redis** for better performance with large-scale applications.

***

### **Final Thoughts**

By following these steps, you've successfully added rate limiting to your Rails app using **rack-attack**. This helps prevent abuse, enhance security, and optimize resource usage efficiently.

Happy coding! 🚀
