Skip to content

Commit 25a5921

Browse files
authored
Default PUMA_PERSISTENT_TIMEOUT to match router 2.0 (heroku#1641)
* Default PUMA_PERSISTENT_TIMEOUT to match router 2.0 Router 2.0 introduced keepalive support. It will close connections idle after 90 seconds https://devcenter.heroku.com/articles/http-routing#keepalives. We want to avoid a situation where they send a request right before puma closes the connection. We can do that by setting it to the same timeout the router uses + some value (such as 5 seconds). Puma 7.0 was just released, and I helped make that value configurable via env var puma/puma#3378. This sets the value for any puma user to do this manually, in their `config/puma.rb`, and for Puma 7+ users they will get that value by default. * Remove hardcoded value from test * Asset PUMA_PERSISTENT_TIMEOUT available from env
1 parent b19faa3 commit 25a5921

4 files changed

Lines changed: 25 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [Unreleased]
44

5+
- Set `export PUMA_PERSISTENT_TIMEOUT=95` to match recommended router 2.0 settings (https://github.com/heroku/heroku-buildpack-ruby/pull/1641)
56

67
## [v319] - 2025-08-27
78

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Ruby apps now have `PUMA_PERSISTENT_TIMEOUT=95` set by default
2+
3+
All Ruby applications now have `PUMA_PERSISTENT_TIMEOUT` environment variable set to a default value of `95`.
4+
5+
Puma [7.0](https://github.com/puma/puma/pull/3378) introduced the ability to configure the `persistent_timeout` value via an environment variable. Router 2.0 uses an idle timeout value of 90s https://devcenter.heroku.com/articles/http-routing#keepalives. To avoid a situation where a request is sent right before Puma closes the connection, the value needs to be slightly higher than the Router's value.
6+
7+
Applications that are not on Puma 7+ can use it manually in their `config/puma.rb` file:
8+
9+
```ruby
10+
# config/puma.rb
11+
12+
# Only required for Puma 6 and below
13+
persistent_timeout(ENV.fetch("PUMA_PERSISTENT_TIMEOUT") || 95)
14+
```
15+
16+
Other web server users can use this as a stable interface to retrieve a suggested idle timeout setting.

lib/language_pack/rack.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ def name
1515
end
1616

1717
def default_config_vars
18-
super.merge({
19-
"RACK_ENV" => env("RACK_ENV") || "production"
20-
})
18+
out = super
19+
out["RACK_ENV"] = env("RACK_ENV") || "production"
20+
out["PUMA_PERSISTENT_TIMEOUT"] = env("PUMA_PERSISTENT_TIMEOUT") || "95"
21+
out
2122
end
2223

2324
def default_process_types

spec/hatchet/ruby_spec.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,13 @@
305305

306306
describe "Rack" do
307307
it "should not overwrite already set environment variables" do
308-
custom_env = "FFFUUUUUUU"
308+
custom_env = SecureRandom.hex(16)
309309
app = Hatchet::Runner.new("default_ruby", config: {"RACK_ENV" => custom_env})
310310

311311
app.deploy do |app|
312-
expect(app.run("env")).to match(custom_env)
312+
environment_variables = app.run("env")
313+
expect(environment_variables).to match(custom_env)
314+
expect(environment_variables).to match("PUMA_PERSISTENT_TIMEOUT")
313315
end
314316
end
315317
end

0 commit comments

Comments
 (0)