{"id":1225,"date":"2026-09-03T10:57:10","date_gmt":"2026-09-03T09:57:10","guid":{"rendered":"https:\/\/ruby-doc.org\/learn\/?p=1225"},"modified":"2026-09-03T14:58:08","modified_gmt":"2026-09-03T13:58:08","slug":"the-rails-app-was-running-but-it-wasnt-working","status":"publish","type":"post","link":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/","title":{"rendered":"The Rails App Was Running, But It Wasn\u2019t Working"},"content":{"rendered":"\n<p class=\"article-attribution wp-block-paragraph\"><strong>Written by <a href=\"https:\/\/ruby-doc.org\/learn\/james-britt\/\">James Britt<\/a><\/strong><br>Technically reviewed by <a href=\"https:\/\/ruby-doc.org\/learn\/jim-freeze\/\">Jim Freeze<\/a> \u00b7 Reviewed 3 September 2026<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A Rails app can look as if it is running smoothly while failing to deliver something customers depend upon. The hosting dashboard is green, each basic uptime check passes and yet some critical tasks simply don&#8217;t get completed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The company in this example is fictional, but the failure pattern is a familiar one in production Rails applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Silent Failure After Deployment<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On Tuesday at 10:14, a small subscription service deployed a routine change. The web process started normally. Customers could log in, see their account information and even edit their profiles. The hosting dashboard indicated that everything was green.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At 10:22, a broken Redis connection left the Sidekiq worker processes active but unable to complete their assigned work. Password-reset emails, receipts and webhook deliveries began piling up silently, invisible to anyone checking the website. At 10:47, a customer contacted support because a reset email had not arrived. That complaint was the first useful signal that something was wrong.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The developer involved now had to stop what they were doing, review logs, check the deployment time, measure queue delays and help support determine how long customers had experienced the problem. While repairing the issue might require only five minutes, finding what went wrong, identifying what it impacted and notifying customers took much longer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is when effective Ruby on Rails monitoring needs to begin. &#8220;Can visitors access the homepage?&#8221; is only one of several questions we need to answer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Define What Healthy Looks Like<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For most Rails apps, I&#8217;d like to see monitoring answer the following three questions:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Is the Rails process running?<\/li>\n\n\n\n<li>Are application dependencies available when requested?<\/li>\n\n\n\n<li>Are asynchronous jobs still processing?<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">We do not need to create a single endpoint to handle these three questions. A fast low-cost liveness check can run regularly. More expensive deeper checks can run less frequently and evaluate a handful of key dependent resources required by the application for its primary purpose.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keeping these checks separate makes an alert easier to interpret. If Rails responds but the dependency check fails, I am probably dealing with an application dependency rather than a non-responsive web process.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Start With Rails&#8217; Built-In \/up Endpoint<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Rails includes a built-in health endpoint at \/up. It returns a successful response when the application has booted without raising an exception and an error response otherwise. The route normally looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>get \"up\" =&gt; \"rails\/health#show\", as: :rails_health_check<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">According to <a href=\"https:\/\/api.rubyonrails.org\/classes\/Rails\/HealthController.html\">the Rails API documentation<\/a>, \/up is defined as a default health check that reports whether the application successfully booted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keep it. It is a useful liveness signal for a load balancer or an external monitor. Just remember what it does not establish: a successful response from \/up does not prove that the database accepts queries, Redis is accessible or background jobs are being processed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create Another Route to Monitor Dependencies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To test the dependencies used by the subscription service, add another route:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>get \"health\", to: \"health#show\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Your controller can test both your database and Redis without revealing internal implementation details:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class HealthController &lt; ActionController::API\n  def show\n    checks = {\n      application: \"ok\",\n      database: database_status,\n      redis: redis_status\n    }\n\n    healthy = checks.values.all? { |value| value == \"ok\" }\n\n    render(\n      json: {\n        status: healthy ? \"ok\" : \"degraded\",\n        checks: checks\n      },\n      status: healthy ? :ok : :service_unavailable\n    )\n  end\n\n  private\n\n  def database_status\n    ActiveRecord::Base.connection.execute(\"SELECT 1\")\n    \"ok\"\n  rescue StandardError\n    \"failed\"\n  end\n\n  def redis_status\n    Sidekiq.redis { |connection| connection.ping }\n    \"ok\"\n  rescue StandardError\n    \"failed\"\n  end\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A typical JSON response should contain minimal data:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"status\": \"ok\",\n  \"checks\": {\n    \"application\": \"ok\",\n    \"database\": \"ok\",\n    \"redis\": \"ok\"\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If Redis isn&#8217;t reachable, the health check returns HTTP 503 Service Unavailable along with a generic &#8220;failed&#8221; state. An external monitor receives a valid signal but users don&#8217;t receive hostnames, credentials or raw exception messages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remove the Redis check <em><a href=\"https:\/\/github.com\/sidekiq\/sidekiq\/issues\/6009\">if the application does not<\/a><\/em> use Sidekiq. If another service is essential to the application&#8217;s core job, test that instead. Developers wishing to modify the ruby code shown here can refer to these <a href=\"https:\/\/ruby-doc.org\/learn\/ruby-code-examples\/\">real-world examples of Ruby code<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avoid Making \/health Overly Complex<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A health endpoint can easily become a laundry list of all of your systems and services. I would recommend against that.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A single call to your app can contact multiple services. There are many potential points of failure. And, you&#8217;re adding unnecessary traffic during a period when one of those systems may be experiencing performance degradation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It&#8217;s usually best to have two separate levels of checks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\/up is an inexpensive, high-frequency liveness check for Rails.<\/li>\n\n\n\n<li>\/health evaluates only the few dependency services needed for your application&#8217;s core operation.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Any optional third-party services can have their own custom checks. Otherwise, a slow analytics service can cause your entire Rails application to appear dead to customers while they are able to continue to use it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also avoid making the public response too verbose. Log files are meant to hold diagnostic details, not expose internal system configuration details to outsiders.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify That Background Jobs Are Processing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Another aspect of the initial example is that pinging Redis indicates that Rails can reach Redis. However, it does not indicate that any of the queued jobs are being processed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One option for closing this gap is to implement a heartbeat job. Run a very small job every few minutes that records when it completes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>class WorkerHeartbeatJob &lt; ApplicationJob\n  queue_as :default\n\n  def perform\n    Rails.cache.write(\n      \"worker_heartbeat_at\",\n      Time.current.iso8601,\n      expires_in: 15.minutes\n    )\n  end\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The health check can verify whether or not this recorded timestamp matches what it expects based on how often this job should occur.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Queue length alone can be misleading. Five hundred jobs may be harmless if workers are clearing them rapidly. Twenty jobs can be serious if the oldest has waited for more than an hour. In practice, the age of unfinished work often tells you more than the number waiting.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test Before Production<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A health check that has only worked while everything else was functioning properly isn&#8217;t ready for production yet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Write a basic request spec that verifies proper behavior:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RSpec.describe \"Application health\", type: :request do\n  it \"returns an OK response\" do\n    get \"\/health\"\n\n    expect(response).to have_http_status(:ok)\n    expect(JSON.parse(response.body)&#91;\"status\"]).to eq(\"ok\")\n  end\nend<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Test edge case scenarios next. Prevent database connections. Simulate Redis going offline. Simulate when a worker heartbeat goes stale. And confirm that if a response is slow enough, it will trigger a timeout-based alert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Don&#8217;t aim to model every possible failure scenario. Instead try modeling the ones you care about most and verifying that they generate meaningful statuses and notify the correct team member.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Monitor From Outside Your App<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">An internal dashboard helps once somebody knows there is a problem. It is much less useful when the application or its network cannot be reached.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For both \/up and \/health endpoints, you should have an external monitor assess both the HTTP status and response time for those endpoints. Also consider assessing if it contains expected values in the response body for \/health. Testing from multiple regions can help distinguish if you&#8217;re seeing an issue due to widespread service disruptions versus regional routing issues.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Include specific actionable items in any alert generated by monitoring. Include which endpoint(s) failed; which tests failed; when did it begin; was it validated through other means; and which customer-visible functions may be impacted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Down&#8221; isn&#8217;t a great starting point.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Use Your Health Check Output to Power Your Status Page<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Monitoring enables detection for your team. Communication enables your customers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">During an incident, developers need to investigate the cause and restore service. They should not have to copy the same update into support replies, social posts and a manually maintained status page.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/devhelm.io\/\">DevHelm<\/a> is one service that bundles status pages with uptime monitoring this way \u2014 checks detect the problem, the status page reflects it, and subscribers get notified, all without someone on the team having to context-switch away from actually fixing things.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the subscription-service example, that closes the loop: the failed check alerts the team, the status page displays the incident, and customers have a trusted place to look before sending another support request.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use language that describes the customer impact rather than the plumbing:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Password-reset emails are delayed.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">That is useful to a customer. &#8220;Redis connection pool degraded&#8221; is mainly useful to the engineer already investigating the cause.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Don\u2019t Train the Team to Ignore Alerts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Simply creating additional checks does not inherently enhance Ruby on Rails monitoring. Creating noise-generating alarms which fire repeatedly for minor, self-healing anomalies trains staff to ignore similar future alarms.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Consider implementing confirmation windows wherever applicable. Send emergency notifications differently than informational notices. A broken checkout experience and an abnormally slow report should not trigger the same response.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After an incident, ask three questions: Did monitoring identify the problem? Was the warning early enough? Did the alert help the person responding?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If a customer still reports the fault first, the monitors are watching the wrong behaviour.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Production Monitoring Checklist<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">&lt;summary&gt;Open the Rails monitoring checklist&lt;\/summary&gt;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Keep \/up as a simple Rails liveness check.<\/li>\n\n\n\n<li>Add \/health for a small number of essential dependencies.<\/li>\n\n\n\n<li>Return meaningful HTTP status codes.<\/li>\n\n\n\n<li>Keep sensitive diagnostic details out of public responses.<\/li>\n\n\n\n<li>Track background-job progress, not only Redis connectivity.<\/li>\n\n\n\n<li>Monitor from outside the Rails application.<\/li>\n\n\n\n<li>Confirm failures before sending disruptive alerts when appropriate.<\/li>\n\n\n\n<li>Describe customer impact clearly on the public status page.<\/li>\n\n\n\n<li>Test failure paths before depending on them.<\/li>\n\n\n\n<li>Review monitoring after every important incident.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Ask the Better Question<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At 10:14, the deployment looked fine. At 10:22, an important part of the application stopped doing useful work. At 10:47, a customer supplied the signal that monitoring had missed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rails had not vanished. The team had measured the easiest behaviour instead of the behaviour customers relied upon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u201cIs the site up?\u201d is a fair first question. The better question is whether Rails booted, its essential dependencies work, background jobs are moving and customers can understand a disruption without chasing the development team.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When those signals are connected, a quiet failure becomes much harder to miss.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Rails app can look healthy while background work has stopped. James Britt explains how health checks, job heartbeats and status pages reveal the failure.<\/p>\n","protected":false},"author":3,"featured_media":1224,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-1225","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":7}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ruby on Rails Monitoring: Health Checks and Status Pages<\/title>\n<meta name=\"description\" content=\"Learn how Ruby on Rails monitoring can catch silent failures using health checks, background-job heartbeats, uptime alerts and public status pages.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ruby on Rails Monitoring: Health Checks and Status Pages\" \/>\n<meta property=\"og:description\" content=\"Learn how Ruby on Rails monitoring can catch silent failures using health checks, background-job heartbeats, uptime alerts and public status pages.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/\" \/>\n<meta property=\"og:site_name\" content=\"Ruby-Doc Learn\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-03T09:57:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-03T13:58:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-on-rails-monitoring-health-checks.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1672\" \/>\n\t<meta property=\"og:image:height\" content=\"941\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"James Britt\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"James Britt\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/\"},\"author\":{\"name\":\"James Britt\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#\\\/schema\\\/person\\\/9e1feb9ed541d2a69da09fb4d10ea07b\"},\"headline\":\"The Rails App Was Running, But It Wasn\u2019t Working\",\"datePublished\":\"2026-09-03T09:57:10+00:00\",\"dateModified\":\"2026-09-03T13:58:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/\"},\"wordCount\":1556,\"publisher\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-on-rails-monitoring-health-checks.png\",\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/\",\"name\":\"Ruby on Rails Monitoring: Health Checks and Status Pages\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-on-rails-monitoring-health-checks.png\",\"datePublished\":\"2026-09-03T09:57:10+00:00\",\"dateModified\":\"2026-09-03T13:58:08+00:00\",\"description\":\"Learn how Ruby on Rails monitoring can catch silent failures using health checks, background-job heartbeats, uptime alerts and public status pages.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#primaryimage\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-on-rails-monitoring-health-checks.png\",\"contentUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-on-rails-monitoring-health-checks.png\",\"width\":1672,\"height\":941,\"caption\":\"A Rails application can appear online even when essential background work has stopped.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/the-rails-app-was-running-but-it-wasnt-working\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"The Rails App Was Running, But It Wasn\u2019t Working\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#website\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/\",\"name\":\"Ruby-Doc Learn\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#organization\",\"name\":\"Ruby-Doc Learn\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-doc-logo-transparent.png\",\"contentUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/ruby-doc-logo-transparent.png\",\"width\":1650,\"height\":305,\"caption\":\"Ruby-Doc Learn\"},\"image\":{\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/#\\\/schema\\\/person\\\/9e1feb9ed541d2a69da09fb4d10ea07b\",\"name\":\"James Britt\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/jgb_self-portrait-20140914-150x150.png\",\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/jgb_self-portrait-20140914-150x150.png\",\"contentUrl\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/jgb_self-portrait-20140914-150x150.png\",\"caption\":\"James Britt\"},\"description\":\"James Britt is a Ruby developer, writer, artist, musician and technologist. He created Ruby-Doc.org in 2002 and served as its long-term maintainer. He operates Neurogami and writes practical Ruby tutorials and code examples for Ruby-Doc Learn.\",\"sameAs\":[\"https:\\\/\\\/jamesbritt.com\\\/\"],\"url\":\"https:\\\/\\\/ruby-doc.org\\\/learn\\\/author\\\/jamesbritt\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ruby on Rails Monitoring: Health Checks and Status Pages","description":"Learn how Ruby on Rails monitoring can catch silent failures using health checks, background-job heartbeats, uptime alerts and public status pages.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/","og_locale":"en_US","og_type":"article","og_title":"Ruby on Rails Monitoring: Health Checks and Status Pages","og_description":"Learn how Ruby on Rails monitoring can catch silent failures using health checks, background-job heartbeats, uptime alerts and public status pages.","og_url":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/","og_site_name":"Ruby-Doc Learn","article_published_time":"2026-09-03T09:57:10+00:00","article_modified_time":"2026-09-03T13:58:08+00:00","og_image":[{"width":1672,"height":941,"url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-on-rails-monitoring-health-checks.png","type":"image\/png"}],"author":"James Britt","twitter_card":"summary_large_image","twitter_misc":{"Written by":"James Britt","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#article","isPartOf":{"@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/"},"author":{"name":"James Britt","@id":"https:\/\/ruby-doc.org\/learn\/#\/schema\/person\/9e1feb9ed541d2a69da09fb4d10ea07b"},"headline":"The Rails App Was Running, But It Wasn\u2019t Working","datePublished":"2026-09-03T09:57:10+00:00","dateModified":"2026-09-03T13:58:08+00:00","mainEntityOfPage":{"@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/"},"wordCount":1556,"publisher":{"@id":"https:\/\/ruby-doc.org\/learn\/#organization"},"image":{"@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#primaryimage"},"thumbnailUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-on-rails-monitoring-health-checks.png","articleSection":["Programming"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/","url":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/","name":"Ruby on Rails Monitoring: Health Checks and Status Pages","isPartOf":{"@id":"https:\/\/ruby-doc.org\/learn\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#primaryimage"},"image":{"@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#primaryimage"},"thumbnailUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-on-rails-monitoring-health-checks.png","datePublished":"2026-09-03T09:57:10+00:00","dateModified":"2026-09-03T13:58:08+00:00","description":"Learn how Ruby on Rails monitoring can catch silent failures using health checks, background-job heartbeats, uptime alerts and public status pages.","breadcrumb":{"@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#primaryimage","url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-on-rails-monitoring-health-checks.png","contentUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-on-rails-monitoring-health-checks.png","width":1672,"height":941,"caption":"A Rails application can appear online even when essential background work has stopped."},{"@type":"BreadcrumbList","@id":"https:\/\/ruby-doc.org\/learn\/the-rails-app-was-running-but-it-wasnt-working\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ruby-doc.org\/learn\/"},{"@type":"ListItem","position":2,"name":"The Rails App Was Running, But It Wasn\u2019t Working"}]},{"@type":"WebSite","@id":"https:\/\/ruby-doc.org\/learn\/#website","url":"https:\/\/ruby-doc.org\/learn\/","name":"Ruby-Doc Learn","description":"","publisher":{"@id":"https:\/\/ruby-doc.org\/learn\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ruby-doc.org\/learn\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ruby-doc.org\/learn\/#organization","name":"Ruby-Doc Learn","url":"https:\/\/ruby-doc.org\/learn\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ruby-doc.org\/learn\/#\/schema\/logo\/image\/","url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-doc-logo-transparent.png","contentUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/ruby-doc-logo-transparent.png","width":1650,"height":305,"caption":"Ruby-Doc Learn"},"image":{"@id":"https:\/\/ruby-doc.org\/learn\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/ruby-doc.org\/learn\/#\/schema\/person\/9e1feb9ed541d2a69da09fb4d10ea07b","name":"James Britt","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/jgb_self-portrait-20140914-150x150.png","url":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/jgb_self-portrait-20140914-150x150.png","contentUrl":"https:\/\/ruby-doc.org\/learn\/wp-content\/uploads\/2026\/09\/jgb_self-portrait-20140914-150x150.png","caption":"James Britt"},"description":"James Britt is a Ruby developer, writer, artist, musician and technologist. He created Ruby-Doc.org in 2002 and served as its long-term maintainer. He operates Neurogami and writes practical Ruby tutorials and code examples for Ruby-Doc Learn.","sameAs":["https:\/\/jamesbritt.com\/"],"url":"https:\/\/ruby-doc.org\/learn\/author\/jamesbritt\/"}]}},"_links":{"self":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts\/1225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/comments?post=1225"}],"version-history":[{"count":4,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts\/1225\/revisions"}],"predecessor-version":[{"id":1281,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/posts\/1225\/revisions\/1281"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/media\/1224"}],"wp:attachment":[{"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/media?parent=1225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/categories?post=1225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ruby-doc.org\/learn\/wp-json\/wp\/v2\/tags?post=1225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}