All articles
Tutorial

How to Deploy a NestJS App to Railway in 10 Minutes

Step-by-step guide to deploying a NestJS + PostgreSQL application to Railway, including environment variables, Dockerfile setup, and custom domains.

March 20, 20267 min read

Railway has become one of the best platforms for deploying backend applications. It's fast, the free tier is generous, and PostgreSQL is built in. This guide walks you through deploying a NestJS application from zero to production in about ten minutes.

Prerequisites

  • A NestJS application in a GitHub repository
  • A Railway account (free tier works)
  • PostgreSQL as your database (Railway provides it)

Step 1: Add a Dockerfile

Railway can detect Node.js projects automatically, but a Dockerfile gives you full control over the build. Here's a production-optimized Dockerfile for NestJS:

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
EXPOSE 8080
CMD ["node", "dist/main"]

This uses a multi-stage build β€” the first stage compiles TypeScript, the second stage copies only the compiled output and production dependencies. The final image is lean and fast to start.

Step 2: Configure Your App to Listen on PORT

Railway assigns a dynamic port via the PORT environment variable. Your NestJS main.ts must read it:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const port = process.env.PORT || 3000;
  await app.listen(port);
  console.log(`Application running on port ${port}`);
}
bootstrap();

Step 3: Create a Railway Project

  1. Go to railway.app and sign in with GitHub
  2. Click New Project β†’ Deploy from GitHub repo
  3. Select your repository
  4. Railway will detect the Dockerfile and start building

Step 4: Add PostgreSQL

  1. In your Railway project, click New β†’ Database β†’ PostgreSQL
  2. Railway creates the database and automatically provides DATABASE_URL
  3. In your NestJS service, reference it: process.env.DATABASE_URL

If you're using Prisma, add a postinstall script to generate the client automatically:

// package.json
"scripts": {
  "postinstall": "prisma generate",
  "build": "nest build"
}

Step 5: Set Environment Variables

In Railway's dashboard, go to your service β†’ Variables and add:

NODE_ENV=production
JWT_SECRET=your-secret-key
FRONTEND_URL=https://your-frontend.vercel.app

Railway automatically injects DATABASE_URL from the PostgreSQL service β€” you don't need to set it manually.

Step 6: Run Prisma Migrations

The safest approach is to run migrations before starting the server. Add this to your Dockerfile CMD or a start script:

CMD ["sh", "-c", "npx prisma migrate deploy && node dist/main"]

Or use Railway's Start Command override in the service settings.

Step 7: Custom Domain

  1. In Railway, go to your service β†’ Settings β†’ Networking β†’ Custom Domain
  2. Enter your domain (e.g., api.yourdomain.com)
  3. Add a CNAME record at your DNS provider pointing to the Railway-provided hostname
  4. Railway provisions an SSL certificate automatically

Monitoring Your Deployment

Railway shows real-time logs in the Deployments tab. If your build fails, the logs will tell you exactly why. Common issues:

  • PORT not set: Make sure your app reads process.env.PORT
  • Prisma client not generated: Add prisma generate to your build step
  • Missing env vars: Check the Variables tab for typos

Automating This With PromptForge

Every project generated by PromptForge includes a production-ready Dockerfile, a railway.json configuration, and a Prisma setup that's compatible with Railway's PostgreSQL. You can go from prompt to deployed API in under 15 minutes β€” no manual configuration required. Try it free.

Ready to build your SaaS with AI?

Generate a complete NestJS + Prisma backend from a single prompt β€” free to try.

Start for free