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.rbruby
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
workersto enable clustered mode for multi-core CPUs. - Set
threadsto 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
systemdorforemanto 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.