Deploying NestJS to Railway
Railway is a PaaS (Platform as a Service) that makes deploying Node.js APIs straightforward. It supports Docker, managed databases, and automatic deployments from GitHub.
Why Railway for APIs
- Zero-config if your app has a
Dockerfileor is a standard Node.js app - Managed PostgreSQL (same region as your app)
- Environment variable management
- Automatic deploys on git push
- Free tier available (hobby projects)
Preparing Your NestJS App
Health Check Endpoint
Railway checks if your app is healthy:
// src/health/health.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('health')
export class HealthController {
@Get()
check() {
return { status: 'ok', timestamp: new Date().toISOString() };
}
}
Production Port
Railway injects PORT as an environment variable:
// src/main.ts
const port = process.env.PORT ?? 3000;
await app.listen(port, '0.0.0.0'); // bind to all interfaces
console.log(`Application running on port ${port}`);
Dockerfile
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY /app/dist ./dist
COPY /app/prisma ./prisma
RUN npx prisma generate
EXPOSE 3000
CMD ["node", "dist/main.js"]
Start Script
// package.json
{
"scripts": {
"start:prod": "node dist/main.js",
"build": "nest build"
}
}
Deploying to Railway
Option A: From GitHub
- Go to railway.app → New Project
- Deploy from GitHub repo
- Railway auto-detects Node.js and runs
npm install && npm run build && npm run start:prod
Option B: Railway CLI
npm install -g @railway/cli
railway login
railway init # creates a new project
railway up # deploy current directory
Environment Variables
In Railway dashboard → Service → Variables:
DATABASE_URL=postgresql://... # auto-set if you add Railway PostgreSQL
JWT_SECRET=your-production-secret
NODE_ENV=production
Or via CLI:
railway variables set JWT_SECRET=secret
railway variables set NODE_ENV=production
Database (Railway PostgreSQL)
Add a database to your project:
- Dashboard → New → Database → PostgreSQL
- Railway auto-injects
DATABASE_URLinto your service
Run migrations on deploy:
// package.json
{
"scripts": {
"start:prod": "npx prisma migrate deploy && node dist/main.js"
}
}
Or as a separate Railway process (more reliable):
# Railway Start Command (in service settings)
npx prisma migrate deploy && node dist/main.js
Custom Domain
- Service → Settings → Domains → Add Domain
- Update DNS: CNAME →
yourservice.up.railway.app - SSL is automatic
GitHub Actions + Railway
# .github/workflows/deploy.yml
- name: Deploy to Railway
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
npm install -g @railway/cli
railway up --service api
Get your RAILWAY_TOKEN from: Railway Dashboard → Account Settings → Tokens.
Monitoring
Railway provides:
- Metrics — CPU, memory, network usage
- Logs — real-time, searchable (last 7 days on free tier)
- Deployments — history with rollback
# View logs via CLI
railway logs --tail
Scaling
# Scale up (more CPU/RAM) in Railway dashboard
# Service → Settings → Resources
# Scale out (multiple instances) — Pro plan
# Service → Settings → Replicas
For most apps, Railway's default 512MB RAM / 0.5 vCPU is sufficient at launch.