Framework Guide
Rails Uptime Monitoring
Set up health check endpoints and uptime monitoring for your Ruby on Rails application. Simple patterns for production-ready monitoring.
Simple Health Route
# config/routes.rb
Rails.application.routes.draw do
get '/health', to: 'health#show'
get '/ready', to: 'health#ready'
end
# app/controllers/health_controller.rb
class HealthController < ApplicationController
skip_before_action :authenticate_user!, raise: false
def show
render json: { status: 'healthy', timestamp: Time.current.iso8601 }
end
def ready
checks = {}
healthy = true
# Check database
begin
start = Time.current
ActiveRecord::Base.connection.execute('SELECT 1')
checks[:database] = {
status: 'ok',
response_time_ms: ((Time.current - start) * 1000).round(2)
}
rescue => e
healthy = false
checks[:database] = { status: 'error', message: e.message }
end
status_code = healthy ? :ok : :service_unavailable
render json: {
status: healthy ? 'healthy' : 'unhealthy',
timestamp: Time.current.iso8601,
checks: checks
}, status: status_code
end
end
Using Rails 7.1+ Built-in Health Check
# Rails 7.1+ has a built-in health check endpoint
# config/routes.rb
Rails.application.routes.draw do
get "up" => "rails/health#show", as: :rails_health_check
end
# This returns 200 OK if the app is running
# Default path: /up
Comprehensive Health Check
# app/controllers/health_controller.rb
class HealthController < ApplicationController
skip_before_action :authenticate_user!, raise: false
skip_before_action :verify_authenticity_token
def ready
checks = {}
healthy = true
# Database check
checks[:database] = check_database
healthy = false unless checks[:database][:status] == 'ok'
# Redis check
checks[:redis] = check_redis
healthy = false unless checks[:redis][:status] == 'ok'
# Sidekiq check
checks[:sidekiq] = check_sidekiq
render json: {
status: healthy ? 'healthy' : 'unhealthy',
timestamp: Time.current.iso8601,
checks: checks,
version: ENV.fetch('APP_VERSION', 'unknown'),
ruby_version: RUBY_VERSION,
rails_version: Rails::VERSION::STRING
}, status: healthy ? :ok : :service_unavailable
end
private
def check_database
start = Time.current
ActiveRecord::Base.connection.execute('SELECT 1')
{
status: 'ok',
response_time_ms: ((Time.current - start) * 1000).round(2)
}
rescue => e
{ status: 'error', message: e.message }
end
def check_redis
start = Time.current
Redis.current.ping
{
status: 'ok',
response_time_ms: ((Time.current - start) * 1000).round(2)
}
rescue => e
{ status: 'error', message: e.message }
end
def check_sidekiq
stats = Sidekiq::Stats.new
{
status: 'ok',
enqueued: stats.enqueued,
processed: stats.processed,
failed: stats.failed
}
rescue => e
{ status: 'error', message: e.message }
end
end
Using okcomputer Gem
# Gemfile
gem 'okcomputer'
# config/initializers/okcomputer.rb
OkComputer::Registry.register "database", OkComputer::ActiveRecordCheck.new
OkComputer::Registry.register "redis", OkComputer::RedisCheck.new(Redis.current)
OkComputer::Registry.register "sidekiq", OkComputer::SidekiqLatencyCheck.new('default', 100)
# Routes are automatically mounted at /okcomputer
# GET /okcomputer - all checks
# GET /okcomputer/database - specific check
Skip Authentication
# For Devise
class HealthController < ApplicationController
skip_before_action :authenticate_user!
end
# For basic auth in production
# config/routes.rb
constraints(->(req) { req.path == '/health' }) do
get '/health', to: 'health#show'
end
Best Practices
- Skip authentication — Health checks need to work without auth
- Check Sidekiq — Background jobs are critical for most Rails apps
- Monitor migrations — Ensure database schema is current
- Add timeouts — Use Timeout.timeout() for dependency checks