Skip to content

PgHero Integration

Date: November 26, 2025
Category: Features / Database
Status: Active

PgHero is integrated as a PostgreSQL performance dashboard, accessible via the CRM at /pghero.

Since the app uses webpack (not Sprockets), PgHero’s assets are copied to the public/ folder for static serving. A Rack::Rewrite rule strips locale prefixes from asset paths.

config/initializers/pghero.rb
PgHero.config_path = Rails.root.join('config', 'pghero.yml')
config/pghero.yml
development:
query_stats:
enabled: true
slow_query_ms: 50
index_suggestions:
enabled: true
explain:
enabled: true
analyze: true # Safe in development
production:
query_stats:
enabled: true
explain:
enabled: false # Never EXPLAIN ANALYZE in production
config/routes/crm.rb
mount PgHero::Engine, at: '/pghero' if defined?(PgHero)
# config/routes.rb - Exclude from locale filter
filter :locale, exclude: %r{/(?:...|pghero|...)/}
  1. Log in to CRM as admin
  2. Navigate to https://crm.warmlyyours.me:3000/pghero
  3. Dashboard shows database health overview
Feature Description
Overview Health checks summary (connections, vacuum, slow queries)
Queries Slow query analysis from pg_stat_statements
Space Table sizes and bloat analysis
Connections Active database connections
Live Queries Currently running queries
Maintenance Vacuum and analyze status
Explain Query plan analysis (EXPLAIN ANALYZE)
Tune PostgreSQL configuration suggestions
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS hypopg; -- For index recommendations

These are created automatically by the Docker init script: docker/pg-init-scripts/05-pghero-extensions.sql

PgHero’s assets are committed to public/ for static serving. They only need to be regenerated when the PgHero gem version is updated:

Terminal window
./script/copy_pghero_assets.sh
git add public/stylesheets/pghero public/javascripts/pghero public/images/pghero
git commit -m "chore(pghero): update assets for pghero X.Y.Z"

Only run this when: PgHero gem version changes in Gemfile.lock

File Purpose
config/initializers/pghero.rb PgHero configuration
config/pghero.yml Database-specific settings
config/routes/crm.rb Route mounting
config/routes.rb Locale exclusion for /pghero
config/initializers/260_redirections.rb Rewrite rule for asset paths
script/copy_pghero_assets.sh Asset extraction (run on gem update)
docker/pg-init-scripts/05-pghero-extensions.sql PostgreSQL extensions
public/stylesheets/pghero/ Static CSS (committed)
public/javascripts/pghero/ Static JS (committed)
public/images/pghero/ Static images (committed)

Ensure /pghero is in the locale exclusion pattern in config/routes.rb.

Verify pg_stat_statements extension is enabled:

SELECT * FROM pg_extension WHERE extname = 'pg_stat_statements';

Verify hypopg extension is enabled:

SELECT * FROM pg_extension WHERE extname = 'hypopg';

Enable pg_stat_statements on your production PostgreSQL server:

-- As superuser (postgres)
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Add to postgresql.conf:
-- shared_preload_libraries = 'pg_stat_statements'
-- pg_stat_statements.track = all
-- Grant access to application user
GRANT pg_read_all_stats TO your_app_user;

⚠️ Important: Enabling pg_stat_statements requires a PostgreSQL restart.

PgHero assets are committed to the repository - no deployment step needed.

If you update the PgHero gem version, regenerate assets locally:

Terminal window
./script/copy_pghero_assets.sh
git add public/stylesheets/pghero public/javascripts/pghero public/images/pghero
git commit -m "chore(pghero): update assets for pghero X.Y.Z"

The config/pghero.yml is already configured for production:

production:
query_stats:
enabled: true
slow_query_ms: 50
index_suggestions:
enabled: true
explain:
enabled: false # Never EXPLAIN ANALYZE in production!

PgHero is protected by admin authentication:

  • Route: authenticate :account, ->(account) { account.is_admin? }
  • Only admins can access /pghero

For replica or read-only database analysis, add to config/pghero.yml:

production:
databases:
primary:
url: <%= ENV['DATABASE_URL'] %>
replica:
url: <%= ENV['DATABASE_REPLICA_URL'] %>
  • PgHero GitHub
  • Performance Profiling Stack
  • PostgreSQL Docker Image