Health checks, restart policies, and zero-downtime deploys on Railway
CI/CD & Deployment Pipelines' own domain covered health checks and zero-downtime deploys as general, platform-agnostic concepts. This lesson is the concrete version: what those same ideas actually look like configured on Railway specifically, and what happens when they're left at their defaults.
Intermediate
3 min read
Health checks: Railway's way of knowing a new deployment is actually ready
A health check is an HTTP path Railway polls after starting a new deployment, waiting for a successful response before considering that deployment actually "up" — the same underlying concept CI/CD's own domain covered generically for any deployment pipeline, here specifically gating whether Railway routes real traffic to the new version yet. A service with no health check configured is considered ready the moment its process starts, which is a real risk for anything with a slow startup (running migrations, warming an in-memory cache) — traffic can arrive before the app is actually able to handle it correctly.
Restart policies: what happens when a service crashes
Restart policy: ON_FAILURE
Max retries: 10
Railway's restart policy determines whether a crashed service is automatically restarted — ON_FAILURE (the sensible default for almost everything) restarts it, up to a configured retry limit; NEVER leaves it down, useful specifically for a one-off job that should genuinely stop rather than loop forever if something's actually broken. A worker or cron job (lesson 7) crash-looping with no retry limit at all can generate real, compounding cost under Railway's usage-based billing (lesson 6) — configuring a sane max-retry count is a real, practical safeguard, not just a nicety.
How a new deployment actually replaces the old one, without downtime
Railway starts the new deployment alongside the still-running old one, waits for the new one's health check to pass, switches routing over, and only then tears down the old deployment — this is the same rolling-deployment pattern CI/CD's own domain covers generically, happening automatically on every deploy rather than requiring a team to hand-build it. Without a correctly-configured health check, this safety mechanism degrades: Railway can route traffic to a deployment that merely started but isn't actually ready yet, reintroducing exactly the downtime risk the whole mechanism exists to prevent.
Why this matters more for a service with real startup work to do
A stateless API with near-instant startup barely benefits from a careful health check, since it's ready almost the moment the process starts anyway. A service running database migrations, loading a large model into memory, or establishing several external connections before it can genuinely serve a request benefits enormously — without an accurate health check, Railway's zero-downtime mechanism has no reliable signal for when that startup work has actually finished.