/ use-cases / monitor-railway-app
How to monitor your Railway app
Railway's healthcheck only runs during a deploy, not after. Here is what that leaves uncovered on a long-lived container and how to monitor it in Fettle.
Why Railway's own signals are not uptime monitoring
Railway will run a healthcheck for you if you configure one: point it at a path on your service, and Railway polls that endpoint for an HTTP 200 while a new deployment is starting, before it switches traffic over. That is a real safety net for bad deploys — the documented behavior is that Railway keeps the previous deployment active until the new one answers, and marks the deploy failed if it never does within the configured window (300 seconds by default).
What it is not is ongoing monitoring. Railway's own docs are explicit that the healthcheck endpoint stops being polled the moment the deployment goes live. From that point on, nothing on Railway's side is asking your app whether it is still answering — only whether the container process is still running at all.
That distinction matters more for Railway than it does for a serverless host, because a Railway service is a long-lived container, not a function invoked per request. Long-lived processes fail in ways a fresh invocation cannot: a connection pool exhausts and every request starts timing out while the process itself never exits, a background worker's event loop deadlocks, a memory leak degrades the app long before it crashes outright. Railway's restart policy — configurable per service as always restart, never, or only on failure — is triggered by the container exiting or crashing. A process stuck in exactly the state above usually does neither, so the policy has nothing to catch.
Railway's status page, at status.railway.com, is a third source people sometimes reach for and it answers a different question again: it tracks incidents in Railway's own platform components — the dashboard, the API, the dev studio and similar — not the availability of any individual app deployed on the platform. It can read all-green while your service is down for reasons that have nothing to do with Railway's infrastructure.
None of this is a design flaw in Railway — a deploy-time healthcheck plus a crash-triggered restart policy is a sensible, well-scoped feature, and the platform's logs and metrics are genuinely useful once you already suspect something is wrong. It just is not the same thing as an external check that keeps asking your app "are you actually working" on a fixed schedule, independent of whether the container process happens to still be alive.
What is worth monitoring
For an app running on Railway, an external check earns its keep exactly where Railway's own tooling stops looking:
- The public URL itself, checked on a schedule that does not depend on the container ever crashing — the same request the healthcheck makes at deploy time, asked again continuously after the deploy is done.
- Any custom domain pointed at the service, since its DNS and registrar sit outside Railway and can drift with nothing appearing in the Railway dashboard.
- The TLS certificate on that custom domain, watched on its own — an HTTP check that only confirms the certificate is currently valid will not warn you before it is close to expiry.
- A route that actually exercises the dependency most likely to wedge the process — a database
connection, a queue, an internal service reached over Railway's private networking — rather
than a bare
/healthpath that returns 200 as long as the web server thread is alive, regardless of whether the app can do anything useful. - Any background worker or scheduled job that runs as a Railway service without a public HTTP endpoint at all — a queue consumer, a nightly batch job. An HTTP monitor cannot reach a service like that; a dead man's switch can. Fettle's heartbeat monitors expect a ping from the job itself on a schedule and alert the moment a ping is late, catching a worker that stalled silently with nothing to fail an HTTP check against.
Checking from a single vantage point also hides regional path problems the same way it would on any platform — worth doing from more than one region if the service has traffic outside wherever Railway happens to host that particular deployment.
How to set it up in Fettle
- Create an API key with write scope from Settings → API Keys, or add the monitor straight from the dashboard.
- Add an HTTP monitor against the public URL — the real domain your users hit, not just the Railway-generated one — and, if the app depends on a database or another internal service, point it at a route that actually touches that dependency rather than a bare liveness path.
- For any worker or cron-style service with no public URL, add a heartbeat instead and have the
job call its ping URL (
https://api.fettle.sh/v1/heartbeat/<token>) as its last line, so a run that never finishes is a late ping instead of silence. - The HTTP monitor from step 2 looks like this from the API:
curl -s -X POST https://api.fettle.sh/v1/monitors \
-H "Authorization: Bearer fettle_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Production (Railway)",
"type": "HTTP",
"target": "https://my-app.up.railway.app",
"interval_seconds": 60,
"timeout_seconds": 10,
"regions": ["eu-central", "us-east"]
}'
interval_seconds has a plan floor and regions a plan cap — an interval Railway's own
deploy-time healthcheck never needs, since it only ever runs once per deploy. Try a check
against your own domain from more than one region, without creating anything, on the
multi-region check tool first. The full walkthrough for creating a
key and reading results back is in the quickstart guide.
Prefer an MCP-aware client to raw curl? Point it at the same account with this one-liner:
{
"mcpServers": {
"fettle": {
"url": "https://api.fettle.sh/mcp",
"headers": { "Authorization": "Bearer fettle_your_key_here" }
}
}
}
Which alerts to wire
A wedged container produces no crash for Railway's restart policy to react to and no failed healthcheck for Railway to roll back, so the alert has to come from outside. Fettle sends alerts by email, Slack, Telegram or a generic webhook — wire the channel your team already gets paged on for production incidents, since the point of this monitor is catching exactly the failure mode Railway's own tooling is not positioned to see.
Two habits keep it from becoming noise. First, set a maintenance window around planned redeploys, so the brief gap while a new deployment's healthcheck is still being polled does not fire a false alert on the monitor watching the same URL from outside. Second, if the app is public-facing, put a status page in front of it — Railway's own status page stays green through an outage specific to your deployment, so your users need somewhere else to look. How many monitors, heartbeats and status pages come with each plan is on the pricing page.
Questions
- Does Railway's healthcheck keep watching my app after it deploys?
- No. Railway's own documentation says the healthcheck endpoint is polled only while a deployment is starting, to decide whether to route traffic to it. It does not monitor that endpoint again once the deployment is live, so anything that goes wrong afterward is invisible to it.
- Will Railway restart my service if it stops responding?
- Railway's restart policy reacts to a container crashing or exiting, and you choose whether that means always, never, or only on failure. A process that is still running but stuck — no exit, no crash — does not trigger it, which is why an external check on the actual response still matters.
- Does Railway's status page tell me if my app is down?
- No — status.railway.com reports on Railway's own platform components, such as the dashboard, the API and the dev studio. A fully green status page is compatible with your specific deployment being unreachable or broken.
Start monitoring in a minute
The free plan checks up to 20 monitors as often as every 2 minutes from 2 regions, and emails you when one breaks. See pricing for the paid intervals, or follow the quickstart to do it from the API.