How to Monitor a Ruby Application: Uptime & Alerts
Production Ruby applications go down. Whether you're running a Rails monolith, a Sinatra microservice, or a Hanami app, knowing about downtime before your users do is the difference between a minor incident and a major crisis.
This guide shows you how to add proper uptime monitoring to any Ruby application using Vigilmon. You'll add a health check endpoint, configure Vigilmon to monitor it, and set up alerts so you get notified the moment something goes wrong.
Why Uptime Monitoring Matters for Ruby Apps
Ruby applications share some common failure modes:
- Memory bloat — long-running Rails processes can balloon and get OOM-killed
- Database connection exhaustion — ActiveRecord connection pools run dry under load
- Slow boot cycles — large Gemfiles mean a crash-and-restart can take 30+ seconds
- Background job queues stalling — Sidekiq workers dying silently
Uptime monitoring catches the symptom (the app stopped responding to HTTP) immediately, so you can dig into the cause before users file bug reports.
Step 1: Add a Health Check Endpoint
A health endpoint is the simplest thing Vigilmon can check. It should return an HTTP 200 when everything is working and a non-200 when something is broken.
Rails
Add a route in config/routes.rb:
# config/routes.rb
get '/health', to: 'health#show'
Create the controller:
# app/controllers/health_controller.rb
class HealthController < ApplicationController
skip_before_action :authenticate_user!, raise: false
def show
checks = {
database: database_ok?,
cache: cache_ok?,
}
status = checks.values.all? ? :ok : :service_unavailable
render json: { status: status, checks: checks }, status: status
end
private
def database_ok?
ActiveRecord::Base.connection.execute('SELECT 1')
true
rescue StandardError
false
end
def cache_ok?
Rails.cache.write('health_check', '1', expires_in: 5.seconds)
Rails.cache.read('health_check') == '1'
rescue StandardError
false
end
end
Sinatra
# app.rb
require 'sinatra'
require 'json'
get '/health' do
content_type :json
db_ok = begin
DB.test_connection # replace with your DB adapter
true
rescue StandardError
false
end
status db_ok ? 200 : 503
{ status: db_ok ? 'ok' : 'degraded', database: db_ok }.to_json
end
Hanami
In Hanami 2.x, add a slice action:
# app/actions/health/show.rb
module MyApp
module Actions
module Health
class Show < MyApp::Action
def handle(request, response)
response.format = :json
response.status = 200
response.body = JSON.generate({ status: 'ok' })
end
end
end
end
end
And register the route in config/routes.rb:
get '/health', to: 'health.show'
Step 2: Test Your Health Endpoint Locally
Before pointing Vigilmon at it, verify the endpoint responds correctly:
curl -i http://localhost:3000/health
# HTTP/1.1 200 OK
# Content-Type: application/json
# {"status":"ok","checks":{"database":true,"cache":true}}
Simulate a failure by stopping your database and re-running curl — you should get a 503.
Step 3: Create a Vigilmon Monitor
- Log in to Vigilmon and go to Monitors → New Monitor
- Set the URL to your production health endpoint:
https://yourapp.com/health - Set the Check interval to 1 or 3 minutes
- Under Expected response, confirm that HTTP 200 is required
- Optionally add a Keyword check — Vigilmon can verify the response body contains
"status":"ok"before considering the check a pass - Save the monitor
Vigilmon will immediately start making GET requests to your endpoint from multiple regions.
Step 4: Integrate Vigilmon Webhook Alerts
For programmatic incident handling — for example, opening a PagerDuty ticket or posting to Slack — use Vigilmon webhooks.
Setting Up the Webhook in Vigilmon
- Go to Alert Channels → New Channel → Webhook
- Paste in your endpoint URL (see below)
- Save and attach the channel to your monitor
Receiving Webhooks in Rails
# config/routes.rb
post '/webhooks/vigilmon', to: 'webhooks#vigilmon'
# app/controllers/webhooks_controller.rb
class WebhooksController < ApplicationController
skip_before_action :verify_authenticity_token
def vigilmon
payload = JSON.parse(request.body.read)
monitor_name = payload['monitor']['name']
event = payload['event'] # 'down' or 'up'
checked_at = payload['checked_at']
if event == 'down'
Rails.logger.error "[Vigilmon] #{monitor_name} is DOWN at #{checked_at}"
# e.g. SlackNotifier.alert(monitor_name)
else
Rails.logger.info "[Vigilmon] #{monitor_name} recovered at #{checked_at}"
end
head :ok
end
end
Always return HTTP 200 to acknowledge receipt. Vigilmon will retry delivery for non-2xx responses.
Step 5: Add a Heartbeat Monitor for Background Jobs
If you run Sidekiq, Delayed::Job, or any background processor, add a heartbeat ping so Vigilmon can detect when job processing stalls — even if the web process stays up.
# config/initializers/vigilmon_heartbeat.rb
if defined?(Sidekiq)
Sidekiq.configure_server do |config|
config.on(:beat) do
# Replace with your Vigilmon heartbeat URL from the monitor settings
heartbeat_url = ENV.fetch('VIGILMON_HEARTBEAT_URL', nil)
Net::HTTP.get(URI(heartbeat_url)) if heartbeat_url
end
end
end
Or with a recurring job using sidekiq-cron:
# config/schedule.yml
vigilmon_heartbeat:
cron: '* * * * *' # every minute
class: VigilmonHeartbeatJob
# app/jobs/vigilmon_heartbeat_job.rb
class VigilmonHeartbeatJob
include Sidekiq::Job
def perform
uri = URI(ENV.fetch('VIGILMON_HEARTBEAT_URL'))
Net::HTTP.get(uri)
end
end
In Vigilmon, create a Heartbeat monitor and set the expected ping interval to 2 minutes. If Vigilmon stops receiving pings, it fires an alert.
Step 6: Configure Alert Escalation
Good alerting has layers:
- Immediate notification — email or Slack when the monitor first fires
- Escalation — if unacknowledged after 10 minutes, notify a second channel or on-call rotation
- Recovery notification — alert when the monitor comes back up
In Vigilmon:
- Go to Monitors → (your monitor) → Alert Channels
- Add multiple channels with different escalation delays
- Enable Recovery alerts so you know when the incident is resolved
Step 7: Add Status Page (Optional)
Vigilmon lets you create a public status page at https://status.yourapp.com. This reduces support load during incidents — users can check the status themselves instead of flooding your inbox.
Enable it from Status Pages → New Page and link your monitors to it.
Summary
| Step | What you did |
|------|-------------|
| 1 | Added /health endpoint to Rails/Sinatra/Hanami |
| 2 | Verified the endpoint returns 200 in normal operation and 503 on failure |
| 3 | Created an HTTP monitor in Vigilmon pointing at the health URL |
| 4 | Set up a webhook alert channel for programmatic incident response |
| 5 | Added a heartbeat monitor for background job health |
| 6 | Configured alert escalation and recovery notifications |
Your Ruby application now has end-to-end uptime visibility. When something goes wrong — database hiccup, OOM kill, deployment gone wrong — you'll know within minutes, not hours.