How to Monitor Your Ruby on Rails App with Uptime Checks and Sidekiq Heartbeats (free)
Your Rails app just went down at 3 AM and you found out when a customer emailed you the next morning. Sound familiar?
Most Rails tutorials cover deployment — but almost none cover what to do after you deploy. By the end of this article you'll have HTTP uptime monitoring, Sidekiq heartbeat checks, Slack alerts, and a public status page — all in under 30 minutes, free.
The two failure modes Rails developers miss
Rails production failures cluster into two patterns that are easy to detect but go unnoticed without the right tooling:
Endpoint outages — your /api/health or root URL starts returning 500s or timing out. Users see a broken page, but you don't know until they complain (or worse, they don't complain and just leave).
Silent background job failures — your Sidekiq jobs stop running. The database stops being updated, emails stop going out, Stripe webhooks stop being processed. No exception is raised. Nothing shows up in your logs. You just quietly stop getting results until something downstream explodes.
Both are fixable with a few lines of code and a free monitoring account.
Step 1: Add a health check endpoint
Add the health_check gem to your Gemfile:
# Gemfile
gem 'health_check'
Run:
bundle install
Mount the engine in your routes:
# config/routes.rb
Rails.application.routes.draw do
mount HealthCheck::Engine, at: '/health'
# ... your other routes
end
Configure what to check:
# config/initializers/health_check.rb
HealthCheck.setup do |config|
config.standard_checks = ['database', 'cache', 'migrations']
config.full_checks = ['database', 'cache', 'migrations', 'email']
end
Now GET /health returns healthy with a 200 when everything is fine and a 500 with details when something is wrong. This single endpoint gives you immediate visibility into your database connection, cache, and migration state.
You can test it locally:
curl http://localhost:3000/health
# healthy
Step 2: Set up HTTP uptime monitoring
With your health endpoint live, point Vigilmon at it:
- Sign up for a free account at vigilmon.online
- Click New Monitor → HTTP
- Enter
https://yourdomain.com/health - Set check interval to 5 minutes (free tier)
- Save
Vigilmon will now ping your endpoint every 5 minutes from multiple locations. If it goes down, you get alerted before your users notice.
You can also monitor your critical API routes directly:
-
https://yourdomain.com/api/v1/ping— confirms the API layer is responding -
https://yourdomain.com/— confirms the frontend is serving
Step 3: Heartbeat monitoring for Sidekiq jobs
HTTP monitoring catches server outages. But what about Sidekiq workers that stop running silently?
The heartbeat pattern: your job pings a URL at the end of every successful run. If Vigilmon stops receiving that ping within the expected interval, it knows the job has stopped or failed.
Here's a Sidekiq worker with a heartbeat ping:
# app/workers/daily_report_worker.rb
class DailyReportWorker
include Sidekiq::Worker
sidekiq_options queue: :default, retry: 3
def perform
# Your actual job logic
generate_daily_report
# Ping the heartbeat URL on success
heartbeat_url = ENV['DAILY_REPORT_HEARTBEAT_URL']
if heartbeat_url.present?
Net::HTTP.get(URI(heartbeat_url))
end
rescue => e
# Don't ping on failure — the absence of a ping IS the alert
Rails.logger.error("DailyReportWorker failed: #{e.message}")
raise
end
private
def generate_daily_report
# your logic here
end
end
For jobs that run on a schedule (via sidekiq-cron or whenever), set the heartbeat URL in your environment:
# .env or your deployment environment
DAILY_REPORT_HEARTBEAT_URL=https://vigilmon.online/heartbeats/your-unique-token
In Vigilmon, create a Heartbeat Monitor:
- Click New Monitor → Heartbeat
- Set the expected interval (e.g. every 24 hours)
- Copy the unique ping URL
- Paste it into your environment as
DAILY_REPORT_HEARTBEAT_URL
Now if your worker fails midway, raises an unhandled exception, or simply stops being enqueued — Vigilmon will alert you within one missed interval.
Works with Sidekiq cron schedules
If you're using sidekiq-cron:
# config/schedule.yml
daily_report:
cron: "0 9 * * *"
class: "DailyReportWorker"
queue: default
The heartbeat approach monitors the actual execution, not just whether the job was enqueued. A cron schedule that runs but immediately errors will still miss its ping, triggering an alert.
Step 4: Webhook alerts to Slack or email
Configure alert delivery in Vigilmon:
For Slack:
- Create an incoming webhook in your Slack workspace
- In Vigilmon, go to Notifications → New Channel → Slack
- Paste your webhook URL
- Enable it on each monitor you want it to cover
For email:
- In Vigilmon, go to Notifications → New Channel → Email
- Enter the address (or distribution list)
- Enable it on your monitors
You'll get alerts like:
🔴 DOWN: yourdomain.com/health
Status: 500 Internal Server Error
From: US-East, EU-West
Started: 3 minutes ago
And recovery notifications:
✅ RECOVERED: yourdomain.com/health is back UP
Downtime: 11 minutes
For the heartbeat monitor:
🔴 MISSED: DailyReportWorker heartbeat
Expected every: 24 hours
Last ping: 26 hours ago
Step 5: Public status page
A public status page lets your users self-serve the "is it just me?" question. It also builds trust — transparency during incidents keeps customers from churning.
In Vigilmon:
- Go to Status Pages → New Status Page
- Name it (e.g. "Acme Status")
- Select the monitors to display
- Save and copy the public URL
You can link to it from your site footer, your README, or your error pages. During an incident, users who hit the status page know the team is aware — they don't need to open a support ticket.
What you've built
| What | How |
|---|---|
| HTTP uptime monitoring |
health_check gem + Vigilmon HTTP monitor |
| Database / cache health |
health_check standard checks |
| Sidekiq job monitoring | Heartbeat ping at end of each worker |
| Instant alerts | Slack or email webhook notifications |
| Public status page | Vigilmon status page |
The full setup costs $0 on Vigilmon's free tier and takes less time than tracking down a silent failure that's been running for two days.
Next steps
- Add a heartbeat for each critical Sidekiq worker, not just the daily ones — treat them like uptime monitors
- Monitor response time trends: a gradual slowdown before a crash is often detectable hours in advance
- Add lograge for structured Rails logs that pair well with monitoring dashboards
Get started free at vigilmon.online.
Top comments (0)