- Introduction
- Features
- Screenshots
- Getting Started
- Authentication
- Data Management
- Separate Database Support
- Testing
- Technology Stack
- Advantages Over Other Solutions
- License
Rails Pulse is a comprehensive performance monitoring and debugging gem that provides real-time insights into your Rails application's health. Built as a Rails Engine, it seamlessly integrates with your existing application to capture, analyze, and visualize performance metrics without impacting your production workload.
Why Rails Pulse?
- Visual: Beautiful, responsive dashboards with actionable insights
- Comprehensive: Monitors requests, database queries, and application operations
- Real-time: Live performance metrics
- Zero Configuration: Works out of the box with sensible defaults
- Lightweight: Minimal performance overhead in production
- Asset Independent: Pre-compiled assets work with any Rails build system
- CSP Compliant: Secure by default with Content Security Policy support
- Interactive dashboard with response time charts and request analytics
- SQL query performance tracking with slow query identification
- Route-specific metrics with configurable performance thresholds
- Week-over-week trend analysis with visual indicators
- Content Security Policy (CSP) compliant with pre-compiled assets
- Flexible authentication system with multiple authentication methods
- Automatic data cleanup with configurable retention policies
- Zero build dependencies - works with any Rails setup
- Zero configuration setup with sensible defaults
- Beautiful responsive interface with dark/light mode
- Smart caching with minimal performance overhead
- Multiple database support (SQLite, PostgreSQL, MySQL)
Add Rails Pulse to your application's Gemfile:
gem 'rails_pulse'Install the gem:
bundle installGenerate the installation files:
rails generate rails_pulse:installLoad the database schema:
rails db:prepareAdd the Rails Pulse route to your application:
# config/routes.rb
Rails.application.routes.draw do
mount RailsPulse::Engine => "/rails_pulse"
# ... your other routes
endRails Pulse automatically starts collecting performance data once installed. Access your monitoring dashboard at:
http://localhost:3000/rails_pulse
Customize Rails Pulse in config/initializers/rails_pulse.rb:
RailsPulse.configure do |config|
# Enable or disable Rails Pulse
config.enabled = true
# Set performance thresholds for routes (in milliseconds)
config.route_thresholds = {
slow: 500,
very_slow: 1500,
critical: 3000
}
# Set performance thresholds for requests (in milliseconds)
config.request_thresholds = {
slow: 700,
very_slow: 2000,
critical: 4000
}
# Set performance thresholds for database queries (in milliseconds)
config.query_thresholds = {
slow: 100,
very_slow: 500,
critical: 1000
}
# Asset tracking configuration
config.track_assets = false # Ignore asset requests by default
config.custom_asset_patterns = [] # Additional asset patterns to ignore
# Rails Pulse mount path (optional)
# Specify if Rails Pulse is mounted at a custom path to prevent self-tracking
config.mount_path = nil # e.g., "/admin/monitoring"
# Route filtering - ignore specific routes from performance tracking
config.ignored_routes = [] # Array of strings or regex patterns
config.ignored_requests = [] # Array of request patterns to ignore
config.ignored_queries = [] # Array of query patterns to ignore
# Data cleanup
config.archiving_enabled = true # Enable automatic cleanup
config.full_retention_period = 2.weeks # Delete records older than this
config.max_table_records = { # Maximum records per table
rails_pulse_requests: 10000,
rails_pulse_operations: 50000,
rails_pulse_routes: 1000,
rails_pulse_queries: 500
}
# Metric caching for performance
config.component_cache_enabled = true
config.component_cache_duration = 1.day
# Multiple database support (optional)
# Uncomment to store Rails Pulse data in a separate database
# config.connects_to = {
# database: { writing: :rails_pulse, reading: :rails_pulse }
# }
endRails Pulse supports flexible authentication to secure access to your monitoring dashboard.
Enable authentication by configuring the following options in your Rails Pulse initializer:
# config/initializers/rails_pulse.rb
RailsPulse.configure do |config|
# Enable authentication
config.authentication_enabled = true
# Where to redirect unauthorized users (optional, defaults to "/")
config.authentication_redirect_path = "/login"
# Define your authentication logic
config.authentication_method = proc {
# Your authentication logic here
}
endRails Pulse works with any authentication system. Here are common patterns:
config.authentication_method = proc {
unless user_signed_in? && current_user.admin?
redirect_to main_app.root_path, alert: "Access denied"
end
}config.authentication_method = proc {
unless session[:user_id] && User.find_by(id: session[:user_id])&.admin?
redirect_to main_app.login_path, alert: "Please log in as an admin"
end
}config.authentication_method = proc {
authenticate_or_request_with_http_basic do |username, password|
username == ENV['RAILS_PULSE_USERNAME'] &&
password == ENV['RAILS_PULSE_PASSWORD']
end
}config.authentication_method = proc {
warden.authenticate!(scope: :admin)
}config.authentication_method = proc {
current_user = User.find_by(id: session[:user_id])
unless current_user&.can_access_monitoring?
render plain: "Forbidden", status: :forbidden
end
}- Production Security: Always enable authentication in production environments
- Admin-only Access: Limit access to administrators or authorized personnel
- Environment Variables: Use environment variables for credentials, never hardcode
- HTTPS Required: Always use HTTPS in production when authentication is enabled
- Regular Access Review: Periodically review who has access to monitoring data
Important: The authentication method runs in the context of the Rails Pulse ApplicationController, giving you access to all standard Rails controller methods like redirect_to, render, session, and any methods from your host application's authentication system.
Rails Pulse provides data cleanup to prevent your monitoring database from growing indefinitely while preserving essential performance insights.
Time-based Cleanup
- Automatically delete performance records older than a specified period
- Configurable retention period (default: 2 days)
- Keeps recent data for debugging while removing historical noise
Count-based Cleanup
- Enforce maximum record limits per table
- Prevents any single table from consuming excessive storage
- Configurable limits for each Rails Pulse table
RailsPulse.configure do |config|
# Enable or disable automatic cleanup
config.archiving_enabled = true
# Time-based retention
config.full_retention_period = 2.weeks
# Count-based retention - maximum records per table
config.max_table_records = {
rails_pulse_requests: 10000, # HTTP requests
rails_pulse_operations: 50000, # Operations within requests
rails_pulse_routes: 1000, # Unique routes
rails_pulse_queries: 500 # Normalized SQL queries
}
endRun cleanup manually:
rails rails_pulse:cleanupCheck current database status:
rails rails_pulse:cleanup_statsSchedule automated cleanup:
# Using whenever gem or similar scheduler
RailsPulse::CleanupJob.perform_later- Time-based Phase: Delete all records older than
full_retention_period - Count-based Phase: If tables still exceed limits, delete oldest remaining records
- Safe Deletion: Respects foreign key constraints (operations → requests → queries/routes)
- Comprehensive Logging: Detailed cleanup statistics and operation logs
This two-phase approach ensures you keep the most valuable recent performance data while maintaining manageable database sizes.
Rails Pulse supports storing performance monitoring data in a separate database. By default, Rails Pulse stores data in your main application database alongside your existing tables.
Use a separate database when you want:
- Isolating monitoring data from your main application database
- Using different database engines optimized for time-series data
- Scaling monitoring independently from your application
- Simplified backup strategies with separate retention policies
For shared database setup (default), no database configuration is needed - simply run rails db:prepare after installation.
To use a separate database, configure the connects_to option in your Rails Pulse initializer:
RailsPulse.configure do |config|
# Single separate database
config.connects_to = {
database: { writing: :rails_pulse, reading: :rails_pulse }
}
# Or primary/replica configuration
config.connects_to = {
database: { writing: :rails_pulse_primary, reading: :rails_pulse_replica }
}
endAdd the corresponding database configurations to your config/database.yml:
# For SQLite
production:
# ... your main database ...
rails_pulse:
adapter: sqlite3
database: storage/rails_pulse_production.sqlite3
migrations_paths: db/rails_pulse_migrate
pool: 5
timeout: 5000
# For PostgreSQL
production:
# ... your main database ...
rails_pulse:
adapter: postgresql
database: myapp_rails_pulse_production
username: rails_pulse_user
password: <%= Rails.application.credentials.dig(:rails_pulse, :database_password) %>
host: localhost
migrations_paths: db/rails_pulse_migrate
pool: 5
# For MySQL
production:
# ... your main database ...
rails_pulse:
adapter: mysql2
database: myapp_rails_pulse_production
username: rails_pulse_user
password: <%= Rails.application.credentials.dig(:rails_pulse, :database_password) %>
host: localhost
migrations_paths: db/rails_pulse_migrate
pool: 5For most installations where Rails Pulse data shares your main database:
rails db:prepareThat's it! The schema loads into your existing database alongside your application tables.
When using a separate database with the configuration above:
rails db:prepareThis automatically loads the Rails Pulse schema on the configured separate database.
The installation command creates db/rails_pulse_schema.rb containing all necessary table definitions. This schema-based approach provides:
- Clean Installation: No migration clutter in new Rails apps
- Database Flexibility: Easy separate database configuration
- Version Compatibility: Schema adapts to your Rails version automatically
- Future Migrations: Schema changes will come as regular migrations when needed
Note: Rails Pulse maintains full backward compatibility. If no connects_to configuration is provided, all data will be stored in your main application database as before.
Rails Pulse includes a comprehensive test suite designed for speed and reliability across multiple databases and Rails versions.
# Run all tests (unit, functional, integration)
rails test:all# Unit tests (models, helpers, utilities)
rails test:unit
# Functional tests (controllers, views)
rails test:functional
# Integration tests (end-to-end workflows)
rails test:integration# Run a specific test file
rails test test/models/rails_pulse/request_test.rb
# Run controller tests
rails test test/controllers/rails_pulse/dashboard_controller_test.rb
# Run helper tests
rails test test/helpers/rails_pulse/application_helper_test.rbTest against multiple databases and Rails versions using the matrix task:
# Test all database and Rails version combinations locally
rails test:matrixThis command tests all combinations of:
- Databases: SQLite3, PostgreSQL, MySQL2
- Rails versions: 7.2, 8.0
-
Copy the environment template:
cp .env.example .env
-
Configure your database credentials in
.env:# PostgreSQL Configuration POSTGRES_USERNAME=your_username POSTGRES_PASSWORD=your_password POSTGRES_HOST=localhost POSTGRES_PORT=5432 # MySQL Configuration MYSQL_USERNAME=root MYSQL_PASSWORD=your_password MYSQL_HOST=localhost MYSQL_PORT=3306
-
Create test databases:
# PostgreSQL createdb rails_pulse_test # MySQL mysql -u root -p -e "CREATE DATABASE rails_pulse_test;"
If you prefer testing individual databases:
# Test with SQLite (default)
rails test:all
# Test with PostgreSQL
DATABASE_ADAPTER=postgresql rails test:all
# Test with MySQL
DATABASE_ADAPTER=mysql2 rails test:allThe GitHub Actions CI automatically tests:
- Databases: SQLite3, PostgreSQL
- Rails versions: 7.2, 8.0
MySQL testing has been moved to local development only for better CI reliability.
- Fast SQLite: Tests use optimized SQLite configurations
- Transaction rollback: Fast test cleanup using database transactions
- Stubbed dependencies: External calls and expensive operations are stubbed
- Sequential execution: Tests run sequentially to avoid race conditions
Rails Pulse is built using modern, battle-tested technologies that ensure reliability, performance, and maintainability:
- CSS Zero - Modern utility-first CSS framework bundled for asset independence
- Stimulus - Progressive JavaScript framework for enhanced interactivity
- Turbo - Fast navigation and real-time updates without full page reloads
- Turbo Frames - Lazy loading and partial page updates for optimal performance
- Rails Charts - Rails wrapper around Apache ECharts
- Lucide Icons - Beautiful, consistent iconography with pre-compiled SVG bundle
- Pre-compiled Assets - All CSS, JavaScript, and icons bundled into the gem
- CSP-Safe Implementation - Secure DOM methods and nonce-based asset loading
- Build System - Node.js-based build process for asset compilation
- Zero External Dependencies - Self-contained assets work with any Rails build system
- Request Store - Thread-safe request-scoped storage for performance data
- Rails Caching - Fragment caching with smart invalidation strategies
- ActiveRecord Instrumentation - Built-in Rails performance monitoring hooks
- Rails Generators - Automated installation and configuration
- Omakase Ruby Styling - Consistent code formatting and style
- No External Dependencies: Everything runs in your Rails application with pre-compiled assets
- Zero Monthly Costs: No subscription fees or usage-based pricing
- Data Privacy: All performance data stays in your database(s)
- Customizable: Full control over metrics, thresholds, and interface
- Asset Independence: Works with any Rails build system (Sprockets, esbuild, Webpack, Vite)
- Visual Interface: Beautiful dashboards instead of log parsing
- Structured Data: Queryable metrics instead of text logs
- Historical Analysis: Persistent storage with trend analysis
- Real-time Monitoring: Live updates and health scoring
- Batteries Included: Complete monitoring solution out of the box
- Proven Architecture: Built on Rails best practices
- Community Driven: Open source with active development
- Professional Design: Production-ready interface
- Rails-Native: Designed specifically for Rails applications
- Developer Experience: Optimized for debugging and development
- Positive Focus: Celebrates good performance alongside problem identification
- Contextual Insights: Deep Rails framework integration for meaningful metrics
- Security First: CSP-compliant by default with secure asset handling
- Zero Build Dependencies: Pre-compiled assets work with any Rails setup
- Flexible Data Storage: Support for multiple database backends (SQLite, PostgreSQL, MySQL)
The gem is available as open source under the terms of the MIT License.

