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
Dockerfilebuilds onnode:24-alpine;CMDispnpm start. packages/cli/src/generators/deploy-scripts.tsprependspnpm -F @repo/database migrateonto thatstartscript, so the schema migrates on every boot.- The schema owner is the frontend app for
fullstack, orapps/backend(EXPOSE 3010) forseparate.
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.
| Variable | Required | Source |
|---|---|---|
DATABASE_URL | Yes | Postgres service or external (Neon / Supabase) |
REDIS_URL | Yes | Redis service or self-hosted (Caching) |
BETTER_AUTH_SECRET | Yes | 32+ char random secret (openssl rand -base64 32) |
API_URL | Yes | The backend's public URL; falls back to the *_PUBLIC_API_URL keys |
INNGEST_APP_ID, INNGEST_EVENT_KEY, INNGEST_BASE_URL | Yes | Background jobs |
BASE_URL, TRUSTED_ORIGINS | Recommended | Production 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
Environment variables
Reverse proxy
Separate backend
API_PORT for independent scaling.