Rails Error Handling Patterns for Production
Rails has opinions about error handling, but production apps need more than the defaults. Here are patterns that work at scale.
Centralized Controller Error Handling
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from ActiveRecord::RecordInvalid, with: :unprocessable
rescue_from ActionController::ParameterMissing, with: :bad_request
private
def not_found(exception)
render json: { error: exception.message }, status: :not_found
end
def unprocessable(exception)
render json: {
error: 'Validation failed',
details: exception.record.errors.full_messages
}, status: :unprocessable_entity
end
def bad_request(exception)
render json: { error: exception.message }, status: :bad_request
end
endCustom Exception Classes
module Errors
class ServiceError < StandardError
attr_reader :code, :status
def initialize(message, code: 'INTERNAL_ERROR', status: :internal_server_error)
@code = code
@status = status
super(message)
end
end
class RateLimitExceeded < ServiceError
def initialize
super('Rate limit exceeded', code: 'RATE_LIMITED', status: :too_many_requests)
end
end
endBackground Job Error Handling
class ProcessOrderJob < ApplicationJob
retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 5
discard_on ActiveRecord::RecordNotFound
def perform(order_id)
order = Order.find(order_id)
OrderProcessor.new(order).process!
rescue PaymentGateway::Error => e
order.update!(status: 'payment_failed', error_message: e.message)
raise # Re-raise for retry
end
endService Object Pattern
class CreateOrder
def call(params)
ActiveRecord::Base.transaction do
order = Order.create!(params)
process_payment(order)
send_confirmation(order)
order
end
rescue Stripe::CardError => e
OpenStruct.new(success: false, error: e.message)
end
endKey Principles
- Let exceptions bubble up — handle at the controller level
- Use `rescue_from` in ApplicationController — consistent error responses
- Retry transient failures in background jobs — network errors are temporary
- Never rescue `Exception` — only rescue
StandardErrorand subclasses
Integrate Bugsly for real-time error tracking. Rails' default error pages hide production issues; Bugsly surfaces them immediately with full request context.
Try Bugsly Free
AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.
Get Started FreeRelated Articles
Why Your Team Ignores Error Alerts (And How to Fix Alert Fatigue)
Error alerts should drive action, not eye-rolls. A practical guide to designing alerts your team will actually respond to.
Read moreLog Levels Explained: DEBUG, INFO, WARN, ERROR — When to Use Each
A practical guide to choosing the right log level — with framework-specific mappings for Python, Java, Node.js, and Go.
Read moreKotlin Production Best Practices
Essential Kotlin best practices for production including null safety, coroutine patterns, sealed classes for errors, and testing strategies.
Read moreSwift Performance Monitoring Best Practices
Monitor Swift application performance with Instruments profiling, memory tracking, network performance, and real-time crash reporting.
Read more