Open-source project
zombocom/rack-timeout avatar
zombocom/rack-timeout

rack-timeout: aborting a slow Rack request with an exception

Abort requests that are taking too long

921 stars159 forksRubyMIT

At a glance

What is it?
Rack::Timeout is a Rack middleware that aborts requests which take too long by raising an exception, with a default service timeout of 15 seconds and five settings you can tune. The README is blunt about its purpose: it is a debug and remediation tool, not a cure for slow code.
Who is it for?
rack-timeout fits a Ruby team that wants a slow request to fail loudly with a stack trace instead of holding a worker open, and that will then chase the specific endpoints its data points at. Skip it if you are looking for a way to make slow code fast, since the README states plainly that it is a debug and remediation tool rather than a solution, and skip it if your deployment has a hard upstream proxy timeout of a different length, because the two have to be coordinated.
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 39 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 October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The middleware raises rather than hangs

Rack::Timeout aborts requests that are taking too long, and it does so by raising an exception. That single sentence is the design decision that matters. In a normal Rack stack, a slow request holds a worker for as long as the downstream code takes, which in a threaded or evented server translates directly into capacity loss that only shows up under load, usually as timeouts somewhere else and rarely as a trace pointing at the actual slow code. The middleware turns that into an error with a backtrace at a known point in the request, attributed to the service timeout. The default is 15 seconds, and the README recommends setting the timeout as low as realistically viable for your application rather than leaving the default in place. The project is a Ruby library distributed as the rack-timeout gem, maintained under the MIT license, and the copyright line records Caio Chassot for 2010 to 2020.

The README calls it a diagnostic, not a solution

The most useful paragraph in the README is the one that says what the tool is not. Rack::Timeout is not a solution to the problem of long running requests, it is a debug and remediation tool, and app developers should track its data and address recurring instances of particular timeouts, for example by refactoring code so it runs faster or offsetting lengthy work to happen asynchronously. This framing is what keeps the middleware from being misapplied. It is a probe that tells you which endpoint is slow, and it is a circuit breaker that stops one slow request from consuming a worker indefinitely. It does not make your code faster and it is not a queue. The documentation folder backs this up with a page on the risks and shortcomings of using Rack::Timeout, which is a more useful signal about the project's maturity than any claim about its stability.

Five settings, and the difference between the first two

The README lists the settings with their defaults and the environment variable that overrides each:

code
service_timeout:   15     # RACK_TIMEOUT_SERVICE_TIMEOUT
wait_timeout:      30     # RACK_TIMEOUT_WAIT_TIMEOUT
wait_overtime:     60     # RACK_TIMEOUT_WAIT_OVERTIME
service_past_wait: false  # RACK_TIMEOUT_SERVICE_PAST_WAIT
term_on_timeout:   false  # RACK_TIMEOUT_TERM_ON_TIMEOUT

service_timeout is the one you will tune first, and the README recommends setting it as low as realistically viable. wait_timeout and wait_overtime relate to how long a request may sit in the server's queue before the service timeout applies, which matters if your server queues requests behind a busy thread. service_past_wait defaults to false, meaning a request that has already waited past the wait timeout is not given the full service budget. term_on_timeout defaults to false, so the middleware raises rather than terminating the worker process. Settings can be passed at middleware initialisation or set through the RACK_TIMEOUT_* environment variables, and middleware parameters take precedence over the environment. The detail pages in the doc folder cover each one, so the five line summary in the README is a starting point rather than the full description.

Rails installs it for you, and skips it in test

For a Rails application the setup is one line in the Gemfile:

ruby
# Gemfile
gem "rack-timeout"

That loads the library and sets it up as a Rails middleware using the default timeout of 15 seconds. The detail that trips people up is in the same paragraph: the middleware is not inserted for the test environment. Your test suite therefore exercises a stack without the timeout, which means a slow request in tests behaves differently from the same request in production, and it also means you will not notice a timeout regression in CI from this middleware alone. If you want to change the timeout, the README points to the RACK_TIMEOUT_SERVICE_TIMEOUT environment variable. There is also a manual route, needed if you removed Rack::Runtime from the middleware stack or want to decide for yourself where Rack::Timeout is inserted:

ruby
# config/initializers/rack_timeout.rb

# insert middleware wherever you want in the stack, optionally pass
# initialization arguments, or use environment variables
Rails.application.config.middleware.insert_before Rack::Runtime, Rack::Timeout, service_timeout: 15

Inserting before Rack::Runtime is the documented position, and inserting earlier gives the middleware more of the request to cover.

Sinatra and plain Rack: call it as early as possible

For a Sinatra application or any other Rack app, the middleware is added in the config.ru file:

ruby
# config.ru
require "rack-timeout"

# Call as early as possible so rack-timeout runs before all other middleware.
# Setting service_timeout or `RACK_TIMEOUT_SERVICE_TIMEOUT` environment
# variable is recommended. If omitted, defaults to 15 seconds.
use Rack::Timeout, service_timeout: 15

The comment carries the reasoning. Position in the stack decides what the timeout covers. Middleware that runs before Rack::Timeout in the stack is outside its measurement, so anything slow there, a logging layer, an authentication step, a proxy hop, will not be caught by the service timeout. Putting it first means the clock covers the whole application. The same principle explains the manual Rails recipe, where you insert before Rack::Runtime rather than at the end. If your slowness lives in a middleware you inserted earlier, moving Rack::Timeout to the front is the first thing to try.

The doc folder is the real product here

The README points to a doc directory with pages on the risks and shortcomings of using Rack::Timeout, understanding the request lifecycle, the exceptions raised by Rack::Timeout, Rollbar fingerprinting, observers, settings and logging. Two of those deserve attention from an evaluator. The exceptions page matters because the raised error becomes part of your application's error handling, and how it is classified determines whether it pages somebody or is silently retried. The Rollbar fingerprinting page matters because a timeout error thrown from a middleware tends to be reported with a generic fingerprint, so a burst of timeouts can flood an error tracker with one undifferentiated group, and the library provides a way to shape that. Observers give a hook for reporting timeouts to your own metrics, which is what the README means by tracking the data. There is also a separate demo repository, rack_timeout_demos, showing the impact of changing the settings and what happens when a timeout is hit.

Versions, licence and running the tests

The README states that this version is compatible with Ruby 2.3 and up, and for Rails apps, Rails 3.x and up, and notes that the basic usage section covers currently supported versions of Ruby, Rack, Rails and Bundler with a Compatibility section at the end for legacy versions. There is an UPGRADING.md file that the README points to for fixing issues when upgrading, which is the document to read before bumping the gem in a large application. The licence is MIT, with an MIT-LICENSE file at the root. The repository has no GitHub releases, so the version you get is whatever the gem publishes rather than a tagged release, and the CHANGELOG.md is the record of what changed. The last push was on 2026-09-14 and the repository is not archived. Contributors run the suite with bundler and rake:

console
bundle
bundle exec rake test

Editorial conclusion

rack-timeout fits a Ruby team that wants a slow request to fail loudly with a stack trace instead of holding a worker open, and that will then chase the specific endpoints its data points at. Skip it if you are looking for a way to make slow code fast, since the README states plainly that it is a debug and remediation tool rather than a solution, and skip it if your deployment has a hard upstream proxy timeout of a different length, because the two have to be coordinated. Before adopting, set RACK_TIMEOUT_SERVICE_TIMEOUT to a value your application can realistically meet, read doc/risks.md for the failures the middleware itself introduces, and confirm the middleware is not inserted in the test environment, since that difference will change how your suite behaves.

Frequently asked questions

What does rack-timeout do when a request takes too long?

It aborts the request by raising an exception. The default service timeout is 15 seconds, and the README recommends setting it as low as realistically viable for your application, either through the RACK_TIMEOUT_SERVICE_TIMEOUT environment variable or as a middleware parameter.

How do I add rack-timeout to a Rails application?

Add gem "rack-timeout" to the Gemfile and it is set up as Rails middleware with the default timeout. The middleware is not inserted for the test environment, and if you have removed Rack::Runtime you can insert it yourself with Rails.application.config.middleware.insert_before Rack::Runtime, Rack::Timeout, service_timeout: 15.

Which settings does rack-timeout expose?

service_timeout defaults to 15, wait_timeout to 30, wait_overtime to 60, service_past_wait to false and term_on_timeout to false. Each has a matching RACK_TIMEOUT_* environment variable, and middleware parameters take precedence over the environment. The doc folder has a settings page with the full description.

Is rack-timeout a way to fix slow requests?

No. The README states that Rack::Timeout is not a solution to the problem of long running requests but a debug and remediation tool, and that developers should track its data and address recurring timeouts, for example by refactoring code or moving lengthy work to run asynchronously.

Where should the Rack::Timeout middleware be placed in the stack?

As early as possible. The README's Sinatra example says to call it early so that rack-timeout runs before all other middleware, and for Rails it recommends inserting before Rack::Runtime. Middleware placed earlier in the stack than Rack::Timeout falls outside what the service timeout measures.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. zombocom/rack-timeout on GitHub
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zombocom-rack-timeout.svg)](https://hysenlabs.com/projects/zombocom-rack-timeout)

Was this useful?