Search docs

Jump between documentation pages.

Railway

Railway auto-detects Node projects from package.json. A config file is optional; add one only when you want to pin the start command, set a health check, run pre-deploy migrations, or switch to a Dockerfile-based build.

When to choose Railway

  • You want the lowest-config push-and-it-runs experience on Node.
  • You want managed Postgres, Redis, or MySQL in the same project.
  • You like environment-per-PR with usage-based billing.

Server entrypoint

ts
// src/server.ts
import { serve } from "@daloyjs/core/node";
import { app } from "./app.js";

serve(app, {
  port: Number(process.env.PORT ?? 3000),
  hostname: "0.0.0.0",
});

railway.json

json
{
  "$schema": "https://railway.com/railway.schema.json",
  "build": {
    "builder": "RAILPACK"
  },
  "deploy": {
    "startCommand": "node dist/server.js",
    "preDeployCommand": ["pnpm run migrate"],
    "healthcheckPath": "/healthz",
    "healthcheckTimeout": 300,
    "restartPolicyType": "ON_FAILURE"
  }
}

Or, equivalently, railway.toml:

toml
[build]
builder = "RAILPACK"

[deploy]
startCommand = "node dist/server.js"
healthcheckPath = "/healthz"
healthcheckTimeout = 300

Deploy

bash
pnpm dlx @railway/cli login
pnpm dlx @railway/cli link
pnpm dlx @railway/cli up

Gotchas

  • Don't override PORT. Railway injects it and the load balancer targets that port.
  • healthcheckTimeout is in seconds. Make it longer than your slowest legitimate startup.
  • Use preDeployCommand for migrations so schema changes run before traffic shifts.

See also