Database Setup

Rails Pulse offers two database setup options - single database (default and recommended) or separate database for complete isolation.

Rails Pulse offers two database setup options: single database (default and recommended) or separate database for complete isolation.

Option 1: Single Database (Default)

Stores Rails Pulse data in your main application database alongside your existing tables. This is the simplest setup and works great for most applications.

Advantages

  • Zero additional configuration required
  • Simpler backup and deployment strategies
  • Works with any database (SQLite, PostgreSQL, MySQL)
  • Easy to get started - just run migrations

Installation

rails generate rails_pulse:install
rails db:migrate

That’s it! Rails Pulse tables are created in your main database and ready to use.

Option 2: Separate Database

Stores Rails Pulse data in a dedicated database, completely isolated from your main application.

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

Installation

Install with the --database=separate flag:

rails generate rails_pulse:install --database=separate

Then uncomment the connects_to option in your Rails Pulse initializer. Without it, all Rails Pulse models keep writing to your primary connection even though the separate database exists:

# config/initializers/rails_pulse.rb
RailsPulse.configure do |config|
  # Single separate database
  config.connects_to = {
    database: { writing: :rails_pulse, reading: :rails_pulse }
  }
end

Add the database configuration to config/database.yml and run:

rails db:prepare

Important: The connects_to setting applies in every environment, so add the rails_pulse entry to each environment in database.yml (development, test, and production). rails db:test:prepare loads the Rails Pulse schema into the test database automatically.

Database Configuration Examples

SQLite Configuration

# config/database.yml
production:
  # ... your main database ...
  rails_pulse:
    adapter: sqlite3
    database: storage/rails_pulse_production.sqlite3
    migrations_paths: db/rails_pulse_migrate
    schema_dump: false
    pool: 5
    timeout: 5000

PostgreSQL Configuration

# config/database.yml
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
    schema_dump: false
    pool: 5

MySQL Configuration

# config/database.yml
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
    schema_dump: false
    pool: 5

Note: schema_dump: false is required. Without it Rails dumps or loads db/rails_pulse_structure.sql and db:migrate can fail with relation already exists. Keep database tasks enabled so rails db:migrate:rails_pulse still runs upgrades. If a structure file already exists, delete it.

Running Tests in CI

In a multi-database setup, the DATABASE_URL environment variable only overrides the primary database configuration. The rails_pulse entry keeps whatever is in database.yml, so if it has no host, the connection falls back to a local socket and fails in CI.

Set the connection details explicitly instead of relying on DATABASE_URL:

# config/database.yml
default: &default
  adapter: postgresql
  host: <%= ENV.fetch("DB_HOST", "localhost") %>
  username: <%= ENV.fetch("DB_USERNAME", "postgres") %>
  password: <%= ENV.fetch("DB_PASSWORD", nil) %>

test:
  primary:
    <<: *default
    database: myapp_test
  rails_pulse:
    <<: *default
    database: myapp_test_rails_pulse
    migrations_paths: db/rails_pulse_migrate
    schema_dump: false
# .github/workflows/ci.yml
env:
  RAILS_ENV: test
  DB_HOST: localhost
  DB_USERNAME: postgres
  DB_PASSWORD: postgres

With this in place, rails db:test:prepare creates and loads both databases.

Primary/Replica Configuration

For high-availability setups, configure Rails Pulse with primary and replica databases:

# config/initializers/rails_pulse.rb
RailsPulse.configure do |config|
  config.connects_to = {
    database: {
      writing: :rails_pulse_primary,
      reading: :rails_pulse_replica
    }
  }
end

Schema Management

The schema file db/rails_pulse_schema.rb defines all Rails Pulse tables in one place. It is loaded by the installation migration (single database) or by db:prepare (separate database), and should not be deleted or edited by hand.

Upgrades ship as migrations. The upgrade generator copies them into db/migrate (single database) or db/rails_pulse_migrate (separate database).

Single databaseSeparate database
First installrails db:migraterails db:prepare
Upgradesrails generate rails_pulse:upgrade then rails db:migraterails generate rails_pulse:upgrade --database=separate then rails db:migrate:rails_pulse

After a schema load, Rails Pulse records any copied migrations as already applied so they do not show as pending.

Do not use db:prepare or db:setup as a substitute for db:migrate:rails_pulse on an existing separate database. They will not run pending migrations. See Upgrading, which also covers the one-time route migration required for 0.4.0.

Next Steps

Advanced Configuration

Customize performance thresholds, tagging, and data cleanup.

View Advanced →

Common Questions

Find answers to frequently asked questions.

View FAQ →