Self-hosted performance monitoring for Rails apps
Rails Pulse is a Rails engine that monitors your app's performance from the inside. It tracks slow requests, N+1 queries, SQL performance, background jobs, and unhandled exceptions. All data stays in your own database, no third-party cloud, no SaaS subscription, no data leaving your servers.
![]() | ![]() |
![]() | ![]() |
Add to your Gemfile:
gem 'rails_pulse'
Run the installer:
bundle install
rails generate rails_pulse:install
rails db:migrate
Mount the dashboard in config/routes.rb:
Rails.application.routes.draw do
mount RailsPulse::Engine => "/rails_pulse"
end
Schedule the background jobs:
RailsPulse::SummaryJob.perform_later # cron: 5 * * * *
RailsPulse::CleanupJob.perform_later # cron: 0 1 * * *
Your dashboard is now at http://localhost:3000/rails_pulse.
From 0.3.3:
bundle update rails_pulse
rails generate rails_pulse:upgrade
rails db:migrate # or: rails db:migrate:rails_pulse
rails rails_pulse:migrate_routes # required — fills Action and merges same-action paths
Restart all processes after migrate. This release changes how routes are stored (method moves off the route onto each request), so mixed old/new processes are not supported.
The upgrade generator appends new settings to config/initializers/rails_pulse.rb without rewriting what you already set. Review with git diff and keep or discard hunks.
Exception tracking is off for existing installs. The generator inserts config.track_exceptions = false; set it to true after migrating to opt in:
config.track_exceptions = true
config.capture_exception_params = true # params are filtered via Rails' filter_parameters
Separate-database hosts: set schema_dump: false on the rails_pulse entry in config/database.yml and delete db/rails_pulse_structure.sql if that file exists.
If you previously added rails-pulse.js / rails-pulse.css to config.assets.precompile, remove those entries — the gem no longer registers dashboard assets with Sprockets (that re-minify OOMs small hosts). Production deploys that use config.asset_host or a CDN-only CSP should run assets:precompile so rails_pulse:install_assets copies digested files into public/assets.
Full install guide: railspulse.com/documentation/installation
Separate database setup: railspulse.com/documentation/database
Rails Pulse works out of the box with sensible defaults. To customise, edit config/initializers/rails_pulse.rb:
RailsPulse.configure do |config|
config.enabled = true
config.request_thresholds = {
slow: 700,
very_slow: 2000,
critical: 4000
}
config.track_jobs = true
config.capture_job_arguments = false # keep false to protect sensitive data
config.track_exceptions = true
config.capture_exception_params = true # params are filtered via Rails' filter_parameters
config.full_retention_period = 30.days
end
Full configuration reference: railspulse.com/documentation/advanced
Rails Pulse has no built-in authentication, you protect the dashboard using your app's existing auth. Add an authentication_method to the initializer:
RailsPulse.configure do |config|
config.authentication_enabled = true
config.authentication_redirect_path = "/login"
config.authentication_method = proc {
unless user_signed_in? && current_user.admin?
redirect_to main_app.root_path, alert: "Access denied"
end
}
end
Authentication guide: railspulse.com/documentation/authentication
Bug reports and pull requests are welcome on GitHub.
Available as open source under the MIT License.
Ruby
80.7%
HTML
8.2%
JavaScript
7.2%
CSS
2.3%
Shell
1.4%
Self-hosted performance monitoring for Rails apps
Rails Pulse is a Rails engine that monitors your app's performance from the inside. It tracks slow requests, N+1 queries, SQL performance, background jobs, and unhandled exceptions. All data stays in your own database, no third-party cloud, no SaaS subscription, no data leaving your servers.
![]() | ![]() |
![]() | ![]() |
Add to your Gemfile:
gem 'rails_pulse'
Run the installer:
bundle install
rails generate rails_pulse:install
rails db:migrate
Mount the dashboard in config/routes.rb:
Rails.application.routes.draw do
mount RailsPulse::Engine => "/rails_pulse"
end
Schedule the background jobs:
RailsPulse::SummaryJob.perform_later # cron: 5 * * * *
RailsPulse::CleanupJob.perform_later # cron: 0 1 * * *
Your dashboard is now at http://localhost:3000/rails_pulse.
From 0.3.3:
bundle update rails_pulse
rails generate rails_pulse:upgrade
rails db:migrate # or: rails db:migrate:rails_pulse
rails rails_pulse:migrate_routes # required — fills Action and merges same-action paths
Restart all processes after migrate. This release changes how routes are stored (method moves off the route onto each request), so mixed old/new processes are not supported.
The upgrade generator appends new settings to config/initializers/rails_pulse.rb without rewriting what you already set. Review with git diff and keep or discard hunks.
Exception tracking is off for existing installs. The generator inserts config.track_exceptions = false; set it to true after migrating to opt in:
config.track_exceptions = true
config.capture_exception_params = true # params are filtered via Rails' filter_parameters
Separate-database hosts: set schema_dump: false on the rails_pulse entry in config/database.yml and delete db/rails_pulse_structure.sql if that file exists.
If you previously added rails-pulse.js / rails-pulse.css to config.assets.precompile, remove those entries — the gem no longer registers dashboard assets with Sprockets (that re-minify OOMs small hosts). Production deploys that use config.asset_host or a CDN-only CSP should run assets:precompile so rails_pulse:install_assets copies digested files into public/assets.
Full install guide: railspulse.com/documentation/installation
Separate database setup: railspulse.com/documentation/database
Rails Pulse works out of the box with sensible defaults. To customise, edit config/initializers/rails_pulse.rb:
RailsPulse.configure do |config|
config.enabled = true
config.request_thresholds = {
slow: 700,
very_slow: 2000,
critical: 4000
}
config.track_jobs = true
config.capture_job_arguments = false # keep false to protect sensitive data
config.track_exceptions = true
config.capture_exception_params = true # params are filtered via Rails' filter_parameters
config.full_retention_period = 30.days
end
Full configuration reference: railspulse.com/documentation/advanced
Rails Pulse has no built-in authentication, you protect the dashboard using your app's existing auth. Add an authentication_method to the initializer:
RailsPulse.configure do |config|
config.authentication_enabled = true
config.authentication_redirect_path = "/login"
config.authentication_method = proc {
unless user_signed_in? && current_user.admin?
redirect_to main_app.root_path, alert: "Access denied"
end
}
end
Authentication guide: railspulse.com/documentation/authentication
Bug reports and pull requests are welcome on GitHub.
Available as open source under the MIT License.
Ruby
80.7%
HTML
8.2%
JavaScript
7.2%
CSS
2.3%
Shell
1.4%