Separate Dashboard
Deploy Rails Pulse on completely separate infrastructure from your main app — ideal for Kubernetes environments and teams that need full isolation.
When to Use This Pattern
This pattern is the right choice when:
- You’re running on Kubernetes and want Rails Pulse in its own pod or as a sidecar
- Your team has compliance or security requirements that mandate infrastructure isolation
- You want zero possibility of Rails Pulse affecting your main app’s memory, CPU, or connection pool
- You’re running multiple app instances and don’t want the dashboard to scale with them
If you just want the dashboard to run as a separate process on the same server, see Standalone Dashboard — it’s simpler and may be all you need.
How It Works
Rails Pulse has two distinct roles:
- Instrumentation — middleware in your main app that captures requests, queries, and jobs and writes them to the database asynchronously. This is lightweight by design (~0.1ms overhead per request).
- Dashboard — a read-only Rack app that serves the Rails Pulse UI and reads from the database.
In the separate instance pattern, these roles run on completely different infrastructure. Your main app handles instrumentation only; the separate instance handles the dashboard.
Main App (instrumentation)
└── writes metrics → Shared Database ← reads metrics ┐
Rails Pulse Instance (dashboard)
Configuration Options
Same Database, Separate Infrastructure (Recommended)
The simplest approach. Both your main app and the Rails Pulse instance connect to the same database — they just run on different servers or pods.
Main app — disable the embedded dashboard:
# config/initializers/rails_pulse.rb
RailsPulse.configure do |config|
config.mount_dashboard = false
end
# config/routes.rb — remove or comment out
# mount RailsPulse::Engine => "/rails_pulse"
Rails Pulse instance — connect to the shared database and start the server:
export DATABASE_URL="postgresql://user:pass@host/myapp_production"
bundle exec rails_pulse_server
Dedicated Rails Pulse Database
For teams that want complete database isolation — no shared connection pool, independent backups, separate credentials.
Add a rails_pulse connection to your main app’s config/database.yml:
production:
primary:
adapter: postgresql
database: myapp_production
# ... other settings
rails_pulse:
adapter: postgresql
database: myapp_rails_pulse # Separate database
migrations_paths: db/rails_pulse_migrate
# ... other settings
The Rails Pulse instance connects to this dedicated database:
export DATABASE_URL="postgresql://user:pass@host/myapp_rails_pulse"
bundle exec rails_pulse_server
Schema setup: When using a dedicated database, run the Rails Pulse install generator on your main app — it will create the necessary tables in the
rails_pulseconnection. See Database Setup for details.
Kubernetes Deployment
Sidecar Pattern
Run the Rails Pulse dashboard container in the same pod as your main app. They share the pod’s environment variables and network namespace, making database credentials easy to pass through.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
image: your-app-image
# ... main app config
- name: rails-pulse
image: your-app-image # Same image — includes the gem
command: ["bundle", "exec", "rails_pulse_server"]
ports:
- containerPort: 3001
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
- name: RAILS_ENV
value: production
- name: SECRET_KEY_BASE
valueFrom:
secretKeyRef:
name: app-secrets
key: secret-key-base
readinessProbe:
httpGet:
path: /health
port: 3001
livenessProbe:
httpGet:
path: /health
port: 3001
Expose the sidecar via a Service and route to it with an Ingress:
apiVersion: v1
kind: Service
metadata:
name: rails-pulse
spec:
selector:
app: myapp
ports:
- port: 3001
targetPort: 3001
Separate Deployment
For stronger isolation, run Rails Pulse as its own Kubernetes Deployment entirely independent of your main app pods.
apiVersion: apps/v1
kind: Deployment
metadata:
name: rails-pulse
spec:
replicas: 1 # Dashboard doesn't need to scale with app instances
selector:
matchLabels:
app: rails-pulse
template:
metadata:
labels:
app: rails-pulse
spec:
containers:
- name: rails-pulse
image: your-app-image
command: ["bundle", "exec", "rails_pulse_server"]
ports:
- containerPort: 3001
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: database-url
- name: RAILS_ENV
value: production
- name: SECRET_KEY_BASE
valueFrom:
secretKeyRef:
name: app-secrets
key: secret-key-base
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
readinessProbe:
httpGet:
path: /health
port: 3001
livenessProbe:
httpGet:
path: /health
port: 3001
---
apiVersion: v1
kind: Service
metadata:
name: rails-pulse
spec:
selector:
app: rails-pulse
ports:
- port: 3001
targetPort: 3001
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rails-pulse
spec:
rules:
- host: pulse.myapp.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rails-pulse
port:
number: 3001
Which to choose: Use the sidecar pattern when you want simpler credential sharing and don’t need the dashboard to survive main app pod restarts. Use a separate deployment when the dashboard needs to stay up independently.
Migration Checklist: Embedded → Separate Instance
Zero-downtime migration steps:
- Deploy the Rails Pulse instance first (pointing at your existing database) — verify the dashboard works at its new URL before touching the main app
- Confirm data is appearing correctly in the new instance
- Update main app config — set
mount_dashboard = falseand remove the engine mount fromroutes.rb - Deploy the main app changes
- Update bookmarks and internal docs with the new dashboard URL
- Remove old nginx/load balancer rules pointing to the embedded dashboard path (if any)
Next Steps
- Standalone Dashboard — simpler option if you don’t need full infrastructure isolation
- Database Setup — configure a dedicated Rails Pulse database
- Authentication — secure your separate instance