rack/rack: the Ruby interface that sits between your server and your framework
A modular Ruby web server interface.
At a glance
- What is it?
- Rack is a specification and a gem that turns an HTTP request into a single Ruby method call. This article covers what it does, how to install it with rackup, and where the abstraction stops being useful.
- Who is it for?
- Adopt Rack if you are writing middleware, building a framework, or need a portable contract between a Ruby app and more than one server. Do not adopt it as a replacement for Rails or Sinatra: Rack gives you the interface, not routing, ORM or templating.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 22 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 September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Rack solves: one contract between servers and Ruby apps
Before Rack, every Ruby web server and every Ruby web framework needed its own adapter code. A framework that worked on one server did not automatically work on another, and a server that supported one framework needed separate glue for the next. Rack replaces that matrix with a single method call. The README describes it as a minimal, modular and adaptable interface that unifies and distills the bridge between web servers, web frameworks and the web application. The exact shape of that call is defined in the Rack Specification, and the README states that all Rack applications should conform to it.
The audience is narrower than the install count suggests. Rack is for people writing middleware, building or maintaining a Ruby web framework, or embedding a Ruby app inside a server they do not control. If you are writing a Rails controller, you are already a Rack user, but you rarely touch the interface directly. If you are writing a Puma configuration, you are on the server side of the same contract.
How the request and response flow actually works
A Rack application is a Ruby object that responds to call and takes one argument, the environment hash. It returns a three-element array: an HTTP status code, a hash of headers, and a body that responds to each. The README's own example is the smallest possible version of this, and it is worth reading literally because the whole architecture is visible in it.
run do |env|
[200, {}, ["Hello World"]]
endEverything else in Rack is middleware wrapped around that call. Middleware is itself a Rack application that holds a reference to the next one, so a stack is just nested call methods. The README lists what ships in the gem: Rack::CommonLogger for Apache-style logfiles, Rack::ConditionalGet for 304 responses, Rack::ContentLength, Rack::ContentType, Rack::Deflater for gzip, Rack::ETag, Rack::Head, Rack::Lint for checking conformance to the specification, Rack::Lock, Rack::MethodOverride, Rack::Recursive, Rack::Reloader, Rack::Runtime, Rack::Sendfile, Rack::ShowException, Rack::ShowStatus, Rack::Static, and Rack::TempfileReaper. Each one uses the same interface, which is why they compose in any order you choose.
The convenience layer sits beside the middleware, not above it. Rack::Request handles query string parsing and multipart handling. Rack::Response generates replies and handles cookies. Rack::MockRequest and Rack::MockResponse let you test a Rack application without a real HTTP round trip, which is the part that makes Rack worth learning even if you never deploy a bare Rack app. Rack::Cascade tries additional applications when one returns a not-found style response. The README's description of Rack::Cascade is cut off mid-sentence in the published text, so the exact fallback condition is one thing to confirm in the specification rather than assume.
Installing rack and running a first app with rackup
The README gives two install paths. The first is a direct gem install, the second adds it to an existing bundle. Both are one line.
# Install it generally:
$ gem install rack
# or, add it to your current application gemfile:
$ bundle add rackTwo features are not in the rack gem itself. If you need Rack::Session or the bin/rackup executable, the README says to add those gems separately. This is a real change from older versions and a common source of confusion after an upgrade.
$ gem install rack-session rackupA first app is a file named config.ru. The README's example returns a fixed 200 with a plain body.
run do |env|
[200, {}, ["Hello World"]]
endRun it with rackup and check it from another shell. The README uses port 9292 for the curl command, which is the default rackup port.
$ gem install rackup
$ rackup
# In another shell:
$ curl http://localhost:9292
Hello WorldIf you see Hello World, the contract is working end to end. If you get a load error mentioning base64, that is the Ruby 3.4 change the README calls out: base64 stops being a default gem, and the fix is to add base64 as a dependency to your project.
Where Rack is the wrong tool
Rack is an interface, not an application framework. It has no router, no ORM, no view layer and no session store in the core gem. If you need those, the README points at frameworks that support the Rack Specification: Camping, Hanami, Ramaze, Padrino, Roda, Ruby on Rails, Rum, Sinatra, Utopia and WABuR. Choosing bare Rack for a product with more than a handful of endpoints means you are signing up to write the routing and request parsing yourself, and Rack will not help you with that.
The portability promise is also narrower than it sounds. The README says that in general any valid Rack app will run the same on all supported servers without changing anything, but it immediately adds that you need to consult the server documentation for features and limitations. Servers differ in concurrency model, in how they handle streaming bodies, and in what they do with file serving. Rack::Sendfile exists precisely because file serving is a place where servers diverge and the interface alone does not paper over it.
Version support is the third boundary. The README's table marks 3.2.x as receiving bug fixes and security patches, 3.1.x as security patches only, 3.0.x as end of support, and 2.2.x as security patches only through April 2027. The README states that Rack 2.2.x is in security maintenance mode and that all support will end in May 2027, and asks users to upgrade to Rack 3.2. Running 3.0.x today means running a version the project no longer supports.
Rack versus a full framework like Rails or Sinatra
The difference is one of layer, not of quality. Rails and Sinatra are built on the Rack Specification, so they are not alternatives to Rack in the sense of replacing it; they are consumers of it. A Sinatra route is registered on top of a Rack application, and a Rails app boots through a Rack server interface. What you choose between is whether you want the routing, conventions and supporting libraries that a framework provides, or whether you want to define the call method yourself and assemble middleware by hand.
The practical test is what you would otherwise rewrite. If your app needs URL routing, parameter coercion, template rendering and a session store, a framework already implements those on top of Rack, and reimplementing them on bare Rack is duplicated work. If your app is middleware, a proxy, an authentication shim, or a component that has to plug into someone else's server, a framework is the wrong size and Rack is the right one. Rack::Lint is the tool that makes the second case tractable, because it checks conformance to the specification rather than to a particular server.
Maintenance, version support and the licence question
The repository is not archived, and the last push was on 2026-09-08. The most recent release listed is v3.2.6 on 2026-04-01, following v3.2.4 on 2025-11-10 and v3.0.9.1 on 2024-02-21. The README's support table is the upgrade cost in one place: 3.2.x gets bug fixes and security patches, 3.1.x gets security patches only, 3.0.x is end of support, and 2.2.x gets security patches only through April 2027. Moving from 2.x to 3.x is not a patch upgrade; the README points at UPGRADE-GUIDE.md and describes 3.0 as containing significant changes.
The licence field on the repository is reported as NOASSERTION, but the repository root contains a file named MIT-LICENSE. That is a signal about intent, not a legal conclusion, and anyone redistributing Rack inside a product should read MIT-LICENSE and SECURITY.md directly rather than rely on the repository metadata. The SECURITY.md file is the documented channel for reporting vulnerabilities, and the README links to it under the version support table.
Editorial conclusion
Adopt Rack if you are writing middleware, building a framework, or need a portable contract between a Ruby app and more than one server. Do not adopt it as a replacement for Rails or Sinatra: Rack gives you the interface, not routing, ORM or templating. Before upgrading, check your current Rack version against the support table, confirm whether you depend on Rack::Session or bin/rackup (both moved to separate gems), and read UPGRADE-GUIDE.md for the 3.0 changes if you are coming from 2.x.
Frequently asked questions
How do I install rack?
The README gives two options: run gem install rack, or run bundle add rack to add it to your application's Gemfile. If you also need Rack::Session or bin/rackup, those ship as separate gems and must be installed with gem install rack-session rackup.
What is a config.ru file and how do I run it?
config.ru is the file that defines a Rack application. The README's example uses run with a block that returns a status, headers and body array. Install the rackup gem and run rackup, then curl http://localhost:9292 to see the response.
Is rack still maintained?
The repository is not archived and the last push was on 2026-09-08. The README's support table shows 3.2.x receiving bug fixes and security patches, 3.1.x receiving security patches only, and 3.0.x at end of support.
Which Rack versions are still supported?
According to the README, 3.2.x gets bug fixes and security patches, 3.1.x gets security patches only, 3.0.x is end of support, and 2.2.x gets security patches only through April 2027. The README asks users to upgrade to Rack 3.2.
What is Rack::Lint used for?
The README lists Rack::Lint among the middleware shipped with Rack and describes it as checking conformance to the Rack Specification. It is the component to reach for when you want to verify your application against the specification rather than against one particular server.
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)