production_rails
Best practices for running Rails in production.
Production Rails
:rocket: Best practices for running Rails in production
This guide covers different concepts you should be familiar with. Recommendations come from personal experience and work at Instacart. A number of open source projects are ones I’ve created. For a comprehensive list of gems, check out Awesome Ruby.
Security
Everyone writing code must be responsible for security. See best practices and how to secure sensitive data.
Errors
Use an error reporting service like Rollbar.
Use Safely to rescue and report exceptions in non-critical code.
Logging
Use a centralized logging service like Papertrail.
Use Lograge to reduce volume. Configure it to add request_id, user_id, and params.
# config/environments/production.rb
config.lograge.enabled = true
config.lograge.custom_options = lambda do |event|
options = event.payload.slice(:request_id, :user_id)
options[:params] = event.payload[:params].except("controller", "action")
options
end
# app/controllers/application_controller.rb
def append_info_to_payload(payload)
super
payload[:request_id] = request.uuid
payload[:user_id] = current_user.id if current_user
end
Audits
Use an auditing library like Audited.
Migrations
Use Strong Migrations to catch unsafe migrations at dev time.
Web Requests
Use compression. If not using a reverse proxy like nginx, use Rack::Deflater.
Use a CDN like Amazon CloudFront to serve assets.
Use Slowpoke for request timeouts.
Background Jobs
Use a high performance background processing framework like Sidekiq with Active Job.
config.active_job.queue_adapter = :sidekiq
Use ActiveJob::TrafficControl to:
- quickly disable jobs
- throttle
- limit concurrency
BadJob.disable!
Use an email delivery service. You can use one that supports both transactional and marketing email like Postmark, or separate ones for each type.
Use Ahoy Email for message history.
AhoyEmail.default_options[:message] = true
Use a CSS inliner like Roadie for styling.
class ApplicationMailer < ActionMailer::Base
include Roadie::Rails::Automatic
end
Caching and Performance
Use Memcached and Dalli for caching.
config.cache_store = :mem_cache_store
Use a library like MemoWise for memoizing.
memo_wise :time_consuming_method
Monitoring
Tracing
Use a performance monitoring service with transaction traces like New Relic or AppSignal.
Uptime
Use an uptime monitoring service like Pingdom or Uptime Robot.
Database
The database is a common bottleneck for Rails apps and deserves some special monitoring attention. There are some dedicated tools for this:
- If you use Postgres, PgHero can help identify issues
- Use Active Record Query Logs to track the origin of SQL queries
Notable Events
Use Notable to track notable requests and background jobs.
- errors
- slow requests, jobs, and timeouts
- 404s
- validation failures
- CSRF failures
- unpermitted parameters
- blocked and throttled requests
Timeouts
One very important place is Active Record. Add to config/database.yml and adjust as needed.
PostgreSQL
production:
connect_timeout: 2
checkout_timeout: 5
variables:
statement_timeout: 5000 # ms
MySQL and MariaDB
production:
connect_timeout: 1
read_timeout: 1
write_timeout: 1
checkout_timeout: 5
variables:
max_execution_time: 5000 # ms
max_statement_time: 5 # sec
Analytics
Use an analytics tool to measure important events. Consider a first-party library like Ahoy, or use a third-party service like Amplitude or Mixpanel.
New Features
Use a feature flipper library like Rollout to easily enable and disable new features without pushing code.
To A/B test features, use a library like Field Test.
Lastly...
Have suggestions? Help make this guide better for everyone.
Also check out Development Rails and Scaling Rails.