0
0
RailsHow-ToBeginner · 4 min read

How to Use Puma in Production with Ruby on Rails

To use puma in production with Ruby on Rails, configure the config/puma.rb file with production settings and start Puma with the RAILS_ENV=production environment. Use a process manager like systemd or foreman to keep Puma running and consider using a reverse proxy like Nginx for handling requests.
📐

Syntax

The config/puma.rb file controls Puma's behavior. Key parts include:

  • workers: Number of worker processes for concurrency.
  • threads: Min and max threads per worker.
  • bind: The socket or port Puma listens on.
  • environment: Sets the Rails environment (e.g., production).
  • pidfile: File to store Puma's process ID.
  • stdout_redirect: Redirects logs to files.

These settings help Puma efficiently serve your Rails app in production.

ruby
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "production" }

pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }

stdout_redirect "log/puma.stdout.log", "log/puma.stderr.log", true

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

Example

This example shows a basic config/puma.rb setup for production with 2 workers and 5 threads each. It preloads the app for faster worker boot and reconnects ActiveRecord on worker start.

Start Puma in production with:

RAILS_ENV=production bundle exec puma -C config/puma.rb
ruby
workers 2
threads 5, 5

preload_app!

port ENV.fetch("PORT") { 3000 }
environment "production"

pidfile "tmp/pids/puma.pid"

stdout_redirect "log/puma.stdout.log", "log/puma.stderr.log", true

on_worker_boot do
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end
Output
Puma starting in cluster mode with 2 workers and 5 threads each on port 3000 in production environment.
⚠️

Common Pitfalls

Common mistakes when using Puma in production include:

  • Not setting preload_app! which can cause slow worker boot.
  • Failing to reconnect ActiveRecord in on_worker_boot, leading to database connection errors.
  • Not using a process manager, so Puma stops unexpectedly.
  • Binding Puma to a port directly without a reverse proxy, which can cause security and performance issues.

Always use environment variables for concurrency settings to adapt to your server.

ruby
## Wrong: Missing preload and on_worker_boot
workers 2
threads 5, 5

port 3000
environment "production"

## Right: Add preload and reconnect
preload_app!
on_worker_boot do
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end
📊

Quick Reference

Tips for using Puma in production:

  • Use workers to enable clustered mode for multi-core CPUs.
  • Set threads to balance concurrency and memory.
  • Use preload_app! for faster worker boot.
  • Reconnect database in on_worker_boot.
  • Run Puma behind Nginx or Apache as a reverse proxy.
  • Use a process manager like systemd or foreman to keep Puma running.

Key Takeaways

Configure Puma with workers and threads in config/puma.rb for production.
Use preload_app! and reconnect ActiveRecord in on_worker_boot for stability.
Run Puma with RAILS_ENV=production and manage it with a process manager.
Use a reverse proxy like Nginx for better performance and security.
Set environment variables to tune concurrency based on your server resources.