Treat a clean exit as a failure for long running services

When a long running service exits with code 0, Railway marks the deployment Completed and the restart policy never fires, so the service is simply down until a person notices and redeploys. I am asking for a serving deployment that exits to be treated as a failure, or at minimum for a distinct status for it plus a per service setting that treats any exit as a failure.

Here is the exact path, which is documented and behaving as designed.

Completed is "the status of the Deployment when the running app exits with a zero exit code", and the deployment actions page restates it: "if your deployment exits successfully (exit code 0), the status will remain Success". On Failure, the default policy, restarts only when a service "stops due to an error, e.g., crashes, exits with a non-zero code". A clean exit is not an error, so nothing restarts. Always would cover it, but Always is not available on Free or trial, which is exactly where the people hitting this tend to be.

The reason this bites is that a surprising number of clean exits are not intentional. A process level error handler that logs and calls process.exit() with no argument exits 0. A library that routes an unhandled rejection into its own error event, where the application registered no listener for that event, ends the process on a path the author never wrote. An async entry point whose top level promise settles lets the event loop drain. In all three cases the code that was supposed to keep serving is gone, the platform was told the work finished successfully, and the dashboard agrees. No crash, no restart, no alert, no email.

What makes it hard to self diagnose is that Completed is doing double duty. A cron job or a one shot task that finishes is Completed, and that is correct and useful. A web server that vanished is also Completed, and that is a lie the platform cannot currently tell apart from the truth. People end up reading their own deploy logs looking for an error that was never printed, because the failure mode is silence.

It is already showing up in help threads. This one is a Node service reporting "Deployment successful" with status COMPLETED rather than ACTIVE while every request 502s, and the first replies go to bind addresses and start commands before the lifecycle question comes up at all: https://station.railway.com/questions/502-application-failed-to-respond-depl-31a870b5

The change I am asking for, in order of preference.

  1. A deployment that has a listening port or a healthcheck configured, and then exits for any reason, is a failure. Mark it failed and honor the restart policy. Railway already knows which deployments are supposed to be serving, because it is routing traffic to them.
  2. If that is too aggressive a default, give exit 0 on a serving deployment its own status, something like Exited, distinct from Completed, and let it trigger the same notification path a crash does. The status alone would have saved most of the threads I have read.
  3. The minimal version: a per service setting, off by default, that says treat any exit as a failure. One toggle, no change to anyone's current behavior, and it gives long running services a way to opt into the semantics they actually want.

Any one of the three would do. The current state asks every developer to independently discover that their crash handler needs to exit non zero, and most of them discover it during an outage.

Under Review

0 Threads mention this feature

0 Replies

Welcome!

Sign in to your Railway account to join the conversation.

Loading...