How to monitor Ruby on Rails
Monitor a Rails app with an uptime check on the built-in /up route and key pages, error tracking through sentry-ruby, traces for slow actions and queries via OpenTelemetry, and the server agent for Puma, memory and logs. Watch the connection pool for ActiveRecord::ConnectionTimeoutError, and Sidekiq separately if you use it.
What can go wrong with Ruby on Rails
- Pending migrations. Code deployed before
db:migrate: in development Rails raisesActiveRecord::PendingMigrationError; in production, queries against missing columns raise and return 500. - Connection pool exhausted. More threads than
poolin database.yml: requests wait and then fail withActiveRecord::ConnectionTimeoutError("could not obtain a connection from the pool"). - Puma request queueing. All threads busy on slow requests; new requests wait in the backlog and latency grows for everyone.
- Memory bloat. Ruby processes grow over time with fragmentation; workers get OOM-killed or swap.
- /up stays green. Rails 7.1's
/upreturns 200 when the app boots; it does not check the database.
The signals that matter, with alert thresholds
| Signal | Alert when | Why it matters |
|---|---|---|
| /up and key pages | non-2xx twice, or p95 > 1 s | What users see. |
| ConnectionTimeoutError | any | Pool too small for the thread count. |
| Exceptions | new issue, or a spike after a deploy | Bugs. |
| Slow actions and queries | new entries at the top | N+1, missing indexes. |
| Memory per Puma worker | steady growth | Bloat or leak. |
| Puma service | not active | Down. |
Thresholds are starting points. Tune them after a week of data: an alert nobody acts on should be raised or removed.
How to check Ruby on Rails by hand
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/up
bin/rails db:migrate:status | grep -w down
bin/rails runner 'p ActiveRecord::Base.connection_pool.stat'
grep -c ConnectionTimeoutError log/production.log
How to watch Ruby on Rails with Vigil
- In New monitor add an Uptime monitor on
/upand on a page that reads from the database (or an App health monitor on a JSON endpoint that checks the DB and Redis). - Create a project under Errors and use its DSN with
sentry-rubyandsentry-rails; set the release so regressions are tied to deploys. - For traces, use the OpenTelemetry Ruby SDK with
opentelemetry-instrumentation-alland the OTLP endpoint (quick start). Actions get latency histograms; queries are ranked by total time with N+1 detection. - Install the server agent, add the Puma unit to the services to watch, ship
log/production.log, and add alog_watchforConnectionTimeoutErrorwith a limit of 1. - Using Sidekiq? Follow how to monitor Sidekiq for queues, retries and the dead set.
Every alert goes to the channels you pick: email, Slack, Telegram, Discord, Microsoft Teams, Pushover, webhooks or on-call paging. Failures are confirmed by a second check before anyone is woken up.
Ruby on Rails monitoring FAQ
Why isn't /up enough?
It proves the app boots, not that it can reach the database, Redis or anything else. Use it for uptime and add a check that exercises the database.
How big should the database pool be?
At least the number of Puma threads per process (RAILS_MAX_THREADS), plus any threads you start yourself. Sidekiq needs its own pool sized to its concurrency.
Can I see slow queries without APM?
Yes, from the database side: enable pg_stat_statements and the agent's database monitoring lists the top queries by total time. APM adds which action ran them.