Skip to main content

puma_phased_restarts

🚀 Zero-Downtime Deploys with Puma Phased Restarts​

When you need to push code without dropping connections, Puma’s phased restart feature lets you reload your Rails app in place. By integrating this with Capistrano, you can perform a phased-restart during your deploy, ensuring new worker processes boot with fresh code while old ones finish serving existing requests.

In your config/puma.rb, enable phased restarts:

# config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

on_worker_boot do
ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end

# allow phased restarts
plugin :tmp_restart

Then add a Capistrano task to call it:

# lib/capistrano/tasks/puma_phased.rake
namespace :puma do
desc 'Phased restart Puma'
task :phased_restart do
on roles(:app) do
execute :bundle, :exec, :pumactl, '-S', shared_path.join('tmp/pids/puma.state'), 'phased-restart'
end
end
end

after 'deploy:publishing', 'puma:phased_restart'

This setup triggers Puma to spin up new workers with the updated code while letting existing workers drain connections gracefully.