Skip to content
← All posts
6 min read Dawid Skłodowski

Monitoring Rails: the metrics that matter

You cannot fix what you cannot see. A guide to monitoring a Rails app in production — the handful of metrics that actually matter, error tracking, structured logs, and alerting on symptoms your users feel rather than noise.

There is a predictable moment in the life of every production app: something is slow or broken, a customer reports it, and you realise you have no idea what is actually happening inside your running system. Monitoring is what turns that helpless moment into a quick diagnosis. But it is easy to do badly — to drown in dashboards full of numbers nobody looks at, or to be paged at 3 a.m. for things that do not matter. Here is a pragmatic guide to monitoring a Rails app: the few metrics that actually tell you something, and how to alert on them sanely.

The metrics that actually matter

You can measure a thousand things; almost all of them are noise. The signals that genuinely tell you whether your app is healthy are few — a useful framing is the “four golden signals” from Google’s SRE practice, adapted for a Rails app:

  • Latency — how long requests take, measured at the percentiles, not the average. The average hides everything: a p50 of 100ms looks great while your p95 is 4 seconds and one user in twenty is suffering. Watch p95 and p99 — the tail is where your unhappy users live, and it is what an average will never show you.
  • Throughput — requests per minute. Not a health signal on its own, but essential context: a latency spike means something different at 10 req/min than at 10,000.
  • Error rate — the percentage of requests returning 5xx. A rising error rate is the most direct “something is broken” signal there is.
  • Saturation — how full your resources are: CPU, memory, database connection pool, and — Rails-specifically — background job queue depth. A queue that is growing faster than it drains is an early warning of trouble that latency alone will not show.

If you watch only these, you will catch the large majority of real problems. Everything else is detail you consult after one of these tells you where to look.

APM: see inside the request

A latency number tells you a request is slow; an APM (application performance monitoring) tool tells you why. Tools like New Relic, Skylight, and Scout instrument your app and break a request down into where the time actually went — controller, database, view rendering, external HTTP calls:

GET /products/42        850 ms
  ├─ ActiveRecord       620 ms   ← the problem is here
  ├─ View rendering     180 ms
  └─ Controller          50 ms

That breakdown is what turns “the product page is slow” into “the product page runs a 600ms query” — and APM will usually point straight at the N+1 query or the missing index causing it. APM is the single highest-value monitoring investment for a Rails app, because it connects a symptom you can see (slow page) to a cause you can fix (a specific slow query). It also surfaces your slowest endpoints and most time-consuming queries across all traffic, which is a ready-made performance to-do list.

Error tracking, separate from logs

The other essential is error tracking — a dedicated service (Sentry, Honeybadger, Rollbar) that captures every exception with its full context: the backtrace, the request parameters, the user, the release. This is distinct from monitoring metrics and distinct from logs, and you want all three. An error tracker aggregates — it groups the same exception across thousands of occurrences, tells you it started after the 14:00 deploy, shows you it affects 3% of checkout attempts, and notifies you proactively. Grepping logs for exceptions, by contrast, is reactive and gives you no aggregation. The discipline that matters: an error tracker only works if you keep the noise down — triage and resolve or mute issues, because an error feed full of ignored exceptions is one nobody reads, and the real one hides in it.

Structured logs you can actually query

Logs are your detailed record of what happened, but Rails’ default logs are designed to be read by a human, one request at a time — useless for answering “how many checkout failures in the last hour?” across a fleet of servers. Two upgrades make logs useful:

  • Make them structured (key-value or JSON), with a consistent request ID threaded through every line of a request (the ActionDispatch::RequestId middleware gives you this), so you can reconstruct a single request’s full story even when many interleave.
  • Ship them to a central store you can search (an ELK stack, or a hosted log service), so “find every 500 with this stack trace across all servers in the last day” is a query, not an ssh-and-grep expedition.

Logs are where you go for the detail once a metric or an error has told you where to look.

Alert on symptoms, not causes — and only on what matters

This is the part teams get wrong, and getting it wrong is worse than no alerting at all, because it produces alert fatigue — so many pages that people stop reading them, and the real incident is missed in the noise. Two rules:

  • Alert on symptoms your users feel, not on internal causes. Page on “error rate above 2%” or “p95 latency above 2s” — things that mean customers are having a bad time. Do not page on “CPU at 80%”, which may be perfectly fine; CPU is a diagnostic metric you look at after a symptom alert, not an alert in itself.
  • Page only on what needs a human now. If an alert does not require someone to wake up and act, it is not a page — make it a dashboard or a daily digest. Every page should be actionable and real. The test: if you would not get out of bed for it, it should not wake you.

A small set of high-quality, symptom-based alerts that fire rarely and always mean something beats a hundred noisy ones every time.

Verdict

Monitoring is what lets you run a Rails app with your eyes open instead of waiting for customers to be your error detector. Watch the few metrics that matter — latency at the percentiles, throughput, error rate, saturation (including job-queue depth) — and ignore the rest until one of them points you somewhere. Use APM to turn “it’s slow” into “this query is slow”, a dedicated error tracker (kept free of noise) to catch and aggregate exceptions, and structured, centralised logs for the detail. Then alert sparingly, on symptoms your users feel, so the page that fires always deserves your attention. Get this in place before the incident, because the worst time to discover you have no visibility is in the middle of the outage you cannot see.