# The Ultimate Guide to Ruby Timeouts: a reference for setting timeouts in Ruby gems

> Ankane's repository collects tested timeout configuration for roughly 150 Ruby gems, from pg and redis to Faraday and Stripe. It is documentation with a test suite, not a library, and its value depends on how closely your gem versions match the examples.

**ankane/the-ultimate-guide-to-ruby-timeouts** — Timeouts for popular Ruby gems

- Repository: https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts
- Stars: 2,501 · Forks: 100
- Language: Ruby
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/ankane-the-ultimate-guide-to-ruby-timeouts

## What problem the Ruby timeouts guide solves

Most Ruby network clients ship without a deadline. The README states the default is no timeout unless otherwise specified. That default is survivable until a dependency stops answering: a request that never returns holds a thread, and in a threaded server it holds whatever it was holding, a database connection, a lock, a worker slot. The README's framing is blunt about which failure is worse, saying an unresponsive service can be worse than a down one because it can tie up your entire system.

The audience is Ruby and Rails engineers who know they should set a timeout and do not know the option name. Every client invents its own vocabulary. One gem wants open_timeout and read_timeout, another wants timeout, another wants a connection pool checkout value, another wants a statement timeout set in SQL rather than in Ruby. The guide's job is to collapse that search into one page per gem.

It is a reference, not a runtime component. There is no gem to add to a Gemfile, no middleware, no monkey patch. The repository is a README plus a test directory, and the README says the examples have been tested. The test directory is the part that matters: it is what separates this from a blog post written from memory.

## How the guide is organised: timeout types, statement timeouts, gems

The README opens with a taxonomy of timeout types, and that taxonomy is the most reusable thing in the repository. Connect (or open) is the time to open a connection. Read (or receive) is the time to receive data after connecting. Write (or send) is the time to send data after connecting. Checkout is the time to take a connection from a pool. Statement is the time to execute a database statement. Lock, request, wait, command and solve cover the remaining cases the listed gems expose.

That list is worth reading before any snippet, because it explains why setting one number is usually wrong. A connect timeout does not bound a slow response, and a read timeout does not bound the wait for a pooled connection. Many of the entries in the guide set two or three of these separately, and the distinction between them is the actual content.

The second structural block is statement timeouts, which the README calls the single most important thing to do for many apps that use a relational database. It covers PostgreSQL, MySQL and MariaDB. The third block is the gem index, grouped into Standard Library, Data Stores, HTTP Clients, Commands, Web Servers, Rack Middleware, Solvers, Distributed Locks, 3rd Party Services and Other. Each entry links to a section with the configuration for that gem.

One editorial stance runs through the whole document: avoid Ruby's Timeout module. The README links to Mike Perham's 2015 post on the subject rather than arguing the case itself. The point is that Timeout interrupts a thread at an arbitrary point, which can leave a connection or a lock in an inconsistent state, whereas a client-level timeout is handled by the code that owns the socket.

## Installing nothing: how to use the guide for a first timeout

There is no install step. The README does not tell you to add a gem, and the repository has no published package. You read it, or you clone it if you want the tests. The homepage field is empty and the README points at the GitHub repository as the place to get it.

A realistic first use is a PostgreSQL-backed Rails app. The README gives a database.yml snippet that sets the statement timeout through connection variables:

```yml
production:
  variables:
    statement_timeout: 5s # or ms, min, etc
```

After deploying that, any statement exceeding the value is cancelled by the server. The README offers a way to confirm the setting is live, a query that sleeps longer than the timeout:

```sql
SELECT pg_sleep(6);
```

If the timeout is set to 5s, that statement should be cancelled rather than returning after six seconds. The guide also notes a role-level alternative, ALTER ROLE myuser SET statement_timeout = '5s';, and a transaction-scoped form using SET LOCAL inside BEGIN and COMMIT.

Migrations are the obvious conflict, since a long index build will trip a five second limit. The README's answer is to make the value an environment variable and override it for the migration command:

```sh
STATEMENT_TIMEOUT=90s rails db:migrate
```

That pattern, a short default in database.yml and a longer value for one command, is the most transferable idea in the statement timeout section. The same shape recurs for MySQL, where the README notes the setting only applies to read-only SELECT statements and is expressed in milliseconds, and for MariaDB.

## Where the guide stops being enough

The examples are tied to gem versions, and the README does not pin them. A snippet that sets an option on Faraday or redis may not match the major version in your lockfile, and nothing in the repository will tell you that. The Appraisals file and the gemfiles directory exist because the test suite runs against more than one dependency set, but the README does not present a compatibility matrix, so you cannot look up your version and get a yes or no.

Coverage is uneven by nature. The index is long, but it is a list of gems someone chose to cover. If your HTTP client or message broker is not in it, the taxonomy still helps you ask the right question, and the answer is still in that gem's own documentation.

The guide also cannot set a timeout for you. A read_timeout of 5 on an HTTP client bounds one request; it does nothing about a retry loop that fires ten of them, or about a queue consumer that processes a job with no deadline of its own. Those are application-level decisions, and the README's scope ends at the client.

Finally, the statement timeout advice is database-specific. The MySQL entry carries an explicit note that max_execution_time applies only to read-only SELECT statements, which means a slow write is not covered by that setting at all. Reading the PostgreSQL section and assuming the same guarantees on MySQL is a mistake the README warns about but cannot prevent.

## Alternatives: per-gem docs, rack-timeout, and the Python and Node editions

The direct alternative is the documentation of each gem you actually use. It is authoritative for your version and it will not go stale, but it is scattered across dozens of projects, each with its own naming, and none of them will tell you that a connect timeout is not a read timeout. The guide's advantage is consolidation and a shared vocabulary; its disadvantage is that it is a second-hand summary that can drift.

A different kind of alternative is rack-timeout, which appears in the guide's own Rack Middleware section. It works at the request level rather than the client level: it bounds how long a request may occupy a server worker, which catches the case where several individually reasonable client calls add up to an unreasonable total. The two are complementary rather than competing. A client timeout stops one socket from hanging; rack-timeout stops the request from hanging. Using rack-timeout as a substitute for client timeouts means you find out about a slow dependency by killing the request that was waiting on it.

If your stack is not Ruby, the README points to sibling repositories for Python, Node, Go, PHP and Rust, maintained under the same account. They share the structure, so the timeout taxonomy carries over even though the option names do not.

## Maintenance, licence and the cost of copying snippets

The repository is not archived and the last push was on 2026-09-07. There are no releases, which fits a project that ships no package: the README is the artifact, and changes to it are the releases. That also means there is no version number to cite when you copy a snippet, so the only way to know whether an example matches your dependencies is to check the gem itself or run the tests.

The licence is MIT, declared in LICENSE.txt at the repository root. For most readers the practical consequence is that copying a configuration snippet into an application is unencumbered; the usual MIT condition about preserving the copyright notice applies to redistributing the source, not to writing open_timeout: 5 in your own initializer. That is a general description of the licence, not legal advice.

The upgrade cost sits with the gems, not with this repository. When you bump Faraday or redis, the option you copied may change name, gain a default, or move to a different object. The guide will not warn you. Treat each snippet as a starting point to verify against the installed version, and treat the test directory as the model for how to verify it.

## Conclusion

Adopt this as a lookup table when you are configuring a Ruby client for the first time and need the exact option name, or when a code review asks why a request has no deadline. Do not adopt it expecting a runtime dependency: nothing is installed, no timeout is enforced at runtime, and a gem version newer than the examples may have renamed or removed the option. Before copying a snippet, open the linked gem documentation for your installed version, and run the repository's own test suite against your Gemfile if you want to know whether the example still holds for you.

## FAQ

### Do I install The Ultimate Guide to Ruby Timeouts as a gem?

No. It is a README with a test directory, not a published library, and the README gives no install step. You read the configuration for your gem and apply it in your own code or configuration files.

### Why does The Ultimate Guide to Ruby Timeouts say to avoid Ruby's Timeout module?

The README states you should avoid Ruby's Timeout module and links to Mike Perham's post on the subject rather than arguing the case itself. The guide's approach is to set timeouts on the client, where the code that owns the connection can handle the failure.

### Does The Ultimate Guide to Ruby Timeouts work for MySQL as well as PostgreSQL?

It covers both, but not identically. The MySQL entry notes that max_execution_time applies only to read-only SELECT statements and is expressed in milliseconds, while the PostgreSQL entry uses statement_timeout with values like 5s.

## Sources

- [ankane/the-ultimate-guide-to-ruby-timeouts on GitHub](https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts)
- [Issues](https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts/issues)
- [License: MIT](https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts/blob/master/LICENSE)
- [README](https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ankane-the-ultimate-guide-to-ruby-timeouts
