GenerateSaaS

Railway

Deploy the node target to Railway straight from your Git repo, with managed Postgres and Redis services and the schema migrating on every boot.

Railway builds and runs the node target directly from your Git repo. It runs the same long-running Docker image documented in Self-hosting with Docker, so both fullstack and separate work and there is no Railway-specific code in the boilerplate.

Deploy

Create a project from your repo: New Project → Deploy from GitHub repo.

Point the service at the owner Dockerfile - the frontend app's for fullstack, apps/backend/Dockerfile (EXPOSE 3010) for separate. Its CMD is pnpm start, with pnpm -F @repo/database run deploy prepended by the CLI, so the schema migrates on every boot.

For a frontend image, set NEXT_PUBLIC_API_URL=https://yourdomain.com/api as a service variable before the first build - Railway exposes variables to Docker builds as build args, and Next.js bakes it into the browser bundle at build time (see Self-hosting with Docker).

Add a database and cache. Add a Postgres service for a managed DATABASE_URL, or supply an external one (Neon or Supabase). Add a Redis service for REDIS_URL, or use Upstash.
Set environment variables 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. Later Git pushes redeploy automatically.
Generate a domain under Settings → Networking → Generate Domain. Railway issues a public URL and routes to the container's exposed port.

Required environment variables

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 / Upstash (Caching)
BETTER_AUTH_SECRETYes32+ char random secret (openssl rand -base64 32)
API_URLYesThe backend's public URL; falls back to the public API URL var
INNGEST_APP_ID, INNGEST_EVENT_KEY, INNGEST_BASE_URLYesBackground jobs
BASE_URL, TRUSTED_ORIGINSRecommendedProduction origin, plus comma-separated origins for auth and CORS
TRUSTED_PROXYNot neededRailway's edge is detected from its own variables - verify per Client IP

Never deploy a --demo build to Railway - its schema step resets the database and force-pushes the schema on every restart.

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.

On this page