tutorial

How to Monitor a Ruby Application: Uptime & Alerts

"Learn how to add uptime monitoring and alerting to your Ruby application — whether you're running Rails, Sinatra, or Hanami — using Vigilmon webhooks and health endpoints."

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

  1. Log in to Vigilmon and go to Monitors → New Monitor
  2. Set the URL to your production health endpoint: https://yourapp.com/health
  3. Set the Check interval to 1 or 3 minutes
  4. Under Expected response, confirm that HTTP 200 is required
  5. Optionally add a Keyword check — Vigilmon can verify the response body contains "status":"ok" before considering the check a pass
  6. 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

  1. Go to Alert Channels → New Channel → Webhook
  2. Paste in your endpoint URL (see below)
  3. 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:

  1. Immediate notification — email or Slack when the monitor first fires
  2. Escalation — if unacknowledged after 10 minutes, notify a second channel or on-call rotation
  3. 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.


Further Reading

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →