rack-attack: installing it blocks nothing until you write a rule
Rack middleware for blocking & throttling
At a glance
- What is it?
- Rack middleware that decides whether to allow, block or throttle a request based on its properties, for Rails and plain Rack applications. The single most important line in the readme is a warning that the middleware does nothing at all until you configure rules, which is the opposite of how a security gem usually behaves.
- Who is it for?
- rack-attack suits a Rails or Rack application that needs request level rate limiting without standing up a separate rate limiting service, and the safelist and throttle model is small enough to read in an afternoon. Two things to know before you rely on it.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- rack/rack-attack5,767 ★ · +4
| Repository | 2026-09-24 | 2026-11-14 |
|---|---|---|
| rack/rack-attack | 5.8k | 5.8k |
4 Stars in the last 51 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
No rules means no blocking and no throttling
The important note sits directly under the instructions for plugging the middleware into the application, and it is worth reading before anything else. By default the middleware will not perform any blocking or throttling until you specifically tell it what to protect against by configuring some rules. That means installation is not protection. The wiring itself is short. A Rails application picks it up by default with no configuration file required to enable it. A plain Rack application needs two lines in the rackup file:
require "rack/attack"
use Rack::AttackDisabling is the mirror image, with Rack::Attack.enabled set to false, which the readme says can be done permanently for a specific environment or temporarily for particular test cases. So there is a switch, and it is a global one on the module rather than a per-environment setting in a config file.
The readme on the default branch documents unreleased behaviour
The first thing in the file is a warning, not a title. It says you are viewing the development branch version of the readme, which might contain documentation for unreleased features, and it points at a different branch for the version consistent with the latest release, a branch named 6-stable. So a reader who installs the gem and then reads the readme they land on is reading documentation for code that may not be in their build. The release history explains why this matters more than it would for a smaller project: the tags are 6.6.1 in April 2022, 6.7.0 in August 2023 and 6.8.0 in October 2025, so the gap between the two most recent minor releases is over two years. When the documentation branch and the release branch have had that long to diverge, the difference between them is rarely cosmetic.
Safelists outrank everything, including blocklists
The precedence rule is stated once and it is absolute: safelists have the most precedence, so any request matching a safelist is allowed despite matching any number of blocklists or throttles. That ordering is what makes the middleware practical, because it means a monitoring or health check can be exempted without reasoning about every rule that might otherwise catch it. There are two convenience forms for address based exemption, one taking a single address string and one taking a subnet string, and a general form taking a name and a block. The block receives a Rack::Request and returns truthy to allow. The readme's own examples include exempting any request carrying a specific authentication header, and exempting loopback addresses on both the IPv4 and IPv6 forms. Note the comment on the second one, which states that blocklists and throttles are skipped entirely for a safelisted request, rather than merely being outvoted.
A fail2ban pattern with per-filter state and a required discriminator
The blocking section offers two named integrations rather than only the raw forms. A fail2ban filter can be used inside a blocklist to block all requests from clients that misbehave, and the pattern is explicitly inspired by the fail2ban project, with a pointer to that project's documentation for how the parameters work. The filter takes a key, a maximum retry count, a find time and a ban time, and it returns truthy if the request fails or if the address is already banned. Where the state lives is a configuration choice: the fail2ban state is stored in a configurable cache, which defaults to Rails.cache if that is present. The readme also carries a constraint that is easy to miss: for multiple filters, each one must go in its own blocklist and must use a unique discriminator, or the counters collide. A second named pattern, Allow2Ban, appears in the table of contents alongside it.
Tracks are named counters over whatever cache you configure
The table of contents includes a Tracks section and a section devoted to cache store configuration, which is where state such as fail2ban counts is kept. That indirection is the whole design and also its sharpest edge. A counter kept in process memory counts per process, so a Rails application running several application servers behind a load balancer enforces the configured limit per server rather than globally, and the number of requests a client can make scales with the number of processes. The cache store section is where a team decides whether that is acceptable, and for a shared counter the cache has to be shared. The defaulting to Rails.cache means the answer depends on what the application has already configured there rather than on this gem.
Throttles ship RateLimit headers for well-behaved clients
The throttling section is a single method taking a name, an options hash and a block. The part with more design thought behind it is in the customizing responses section, which covers RateLimit headers for well-behaved clients. A client that respects those headers can back off on its own instead of consuming a full allowance and then being rejected, and the readme frames the headers as something emitted for the clients that behave. That inverts the usual failure mode of rate limiting, where a well-behaved client and a misbehaving one are indistinguishable to the server until the limit is hit. The readme also has separate sections for logging and instrumentation, and the examples directory contains an instrumentation file alongside the basic configuration file, so hooking the counters into an application's existing metrics is a supported path rather than something to build.
Appraisals generate the gemfiles directory for testing across dependencies
The repository carries an Appraisals file and a gemfiles/ directory, which is the Appraisal gem's pattern for testing one library against several dependency sets rather than only the newest. The Gemfile sits alongside them with a Rakefile and a rubocop configuration, and there is a separate spec directory holding the tests. For a middleware whose behaviour depends on the Rack version and on framework integration, that arrangement is close to a requirement rather than a nicety: a throttle that reads a header Rack changed, or a request object whose IP resolution moved, would pass on the newest dependency set and fail on an older one. The examples directory is small, two files, one for the base configuration and one for instrumentation, which means the readme rather than the examples carries most of the configuration surface.
Editorial conclusion
rack-attack suits a Rails or Rack application that needs request level rate limiting without standing up a separate rate limiting service, and the safelist and throttle model is small enough to read in an afternoon. Two things to know before you rely on it. Out of the box it performs no blocking and no throttling whatsoever, so the protection only exists once you write rules, and an application that installs the gem and stops there is unprotected while looking protected. And the readme on the default branch is the development version, which may document behaviour that is not in the release you installed. A team that needs distributed rate limiting across several application servers has to read the cache store section carefully, because the counters live wherever you put them.
Frequently asked questions
What does rack-attack do in a Rails application?
It is Rack middleware for blocking and throttling abusive requests, deciding whether to allow, block or throttle based on properties of the request. A Rails application picks it up by default, and rules are written in an initializer file, with safelists, blocklists and throttles defined by calling public methods on the module.
Does rack-attack block requests by default after installation?
No. The readme states that by default it will not perform any blocking or throttling until you specifically tell it what to protect against by configuring rules. The middleware can be disabled entirely by setting Rack::Attack.enabled to false, permanently for an environment or temporarily for particular test cases.
How do I install rack-attack?
Add gem "rack-attack", "~> 6.8" to the Gemfile and run bundle, or install it directly with gem install rack-attack. For a plain Rack application you also need require "rack/attack" and use Rack::Attack in the rackup file. Rails applications use it by default.
What is the difference between a safelist and a blocklist in rack-attack?
Safelists have the most precedence, so a request matching a safelist is allowed despite matching any number of blocklists or throttles, and those rules are skipped entirely rather than outvoted. Both also have a general form taking a name and a block that receives a Rack::Request and returns truthy to allow or to block respectively.
Where is rack-attack release documentation kept?
The readme warns that the version on the default branch is the development one and may document unreleased features, pointing instead at a branch named 6-stable for the version consistent with the latest release. The tags are 6.6.1, 6.7.0 and 6.8.0, with over two years between the two most recent minor releases.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rack-rack-attack)Star history chart for your README
[](https://hysenlabs.com/projects/rack-rack-attack)Was this useful?