GenerateSaaS

Railway

Deploy the Docker container to Railway. Build straight from your Git repo with managed Postgres and Redis, and migrate the schema on every deploy.

Railway is a managed container platform that builds and runs the node deploy target directly from your Git repo. The boilerplate has no Railway-specific code - Railway runs the same long-running Docker image documented in Self-hosting with Docker, so both fullstack and separate work.

How the build maps to Railway

Railway is a long-running runtime, so the CLI's deploy wiring applies unchanged.

  • The owner app's Dockerfile builds on node:24-alpine; CMD is pnpm start.
  • packages/cli/src/generators/deploy-scripts.ts prepends pnpm -F @repo/database migrate onto that start script, so the schema migrates on every boot.
  • The schema owner is the frontend app for fullstack, or apps/backend (EXPOSE 3010) for separate.

Never deploy a --demo build to Railway. The --demo flag swaps the boot-time schema step for a destructive reset && push --force that wipes the database on every restart.

Deploy

Create a project from your repo. In the Railway dashboard, New Project → Deploy from GitHub repo and select your repository.

Confirm the build. Railway auto-detects the Dockerfile in the deployable app. For separate, point the service at apps/backend/Dockerfile; for fullstack, point it at the frontend app's Dockerfile.

Add a database and cache. Add a Postgres service for a managed DATABASE_URL, or supply an external one (Neon, Supabase). Add a Redis service for REDIS_URL, or use Upstash.

Set environment variables. Add the variables below under the service's Variables tab. Reference another service's values with Railway's ${{ }} syntax (e.g. ${{ Postgres.DATABASE_URL }}).

Deploy. Railway builds the image and runs pnpm start; the schema migrates before the server binds. Subsequent Git pushes redeploy automatically.

Generate a domain. Under Settings → Networking → Generate Domain, Railway issues a public URL and routes traffic to the container's exposed port.

Required environment variables

Set these on the service that owns the database (DATABASE_URL only needs to live on the schema-owner service). Full list in Environment variables.

VariableRequiredSource
DATABASE_URLYesPostgres service or external (Neon / Supabase)
REDIS_URLYesRedis service or self-hosted (Caching)
BETTER_AUTH_SECRETYes32+ char random secret (openssl rand -base64 32)
API_URLYesThe backend's public URL; falls back to the *_PUBLIC_API_URL keys
INNGEST_APP_ID, INNGEST_EVENT_KEY, INNGEST_BASE_URLYesBackground jobs
BASE_URL, TRUSTED_ORIGINSRecommendedProduction origin + comma-separated allowed origins for auth and CORS

The container's HEALTHCHECK probes the listening port with a generous start period, so Railway holds traffic until the boot-time migration finishes - no manual readiness gate needed.

Next steps

On this page