Deploy Instructions

NestJS Backend API for GoGrab Space platform - Architecture, Best Practices, and Common Issues

Backend API Deployment Instructions

Last Updated: October 16, 2025
API Version: 1.0.0
Framework: NestJS 10.x
Target Platforms: Railway, Google Cloud Run, Google App Engine


📋 Table of Contents

  1. Deployment Options Comparison
  2. Recommended Approach: Railway (Easiest)
  3. Alternative: Google Cloud Run (Best for Scale)
  4. Alternative: Google App Engine
  5. Environment Variables Setup
  6. Pre-Deployment Checklist
  7. Post-Deployment Configuration
  8. Monitoring and Maintenance
  9. Troubleshooting

🎯 Deployment Options Comparison

Feature Railway Google Cloud Run Google App Engine
Ease of Setup ⭐⭐⭐⭐⭐ Easiest ⭐⭐⭐⭐ Easy ⭐⭐⭐ Medium
Cost (Low Traffic) $5-20/mo $0-10/mo (pay-per-use) $20-50/mo
Cost (High Traffic) $50-200/mo $50-500/mo (scales) $100-1000/mo
Auto-Scaling ✅ Yes (1-10 instances) ✅ Yes (0-1000+) ✅ Yes (1-automatic)
Cold Start ❌ No (always on) ⚠️ Yes (<1s) ❌ No (always on)
Deploy Time 3-5 min 2-3 min 5-10 min
GitHub Integration ✅ Built-in ✅ Via Cloud Build ✅ Via Cloud Build
Custom Domain ✅ Free SSL ✅ Free SSL ✅ Free SSL
MongoDB Atlas ✅ Easy ✅ Easy ✅ Easy
Redis Support ✅ Built-in add-on ✅ Memorystore ✅ Memorystore
Environment Variables ✅ GUI + CLI ✅ GUI + CLI ✅ app.yaml
Logs & Monitoring ✅ Built-in ✅ Cloud Logging ✅ Cloud Logging
Best For Rapid deployment, MVP Production scale, cost optimization Enterprise, existing GCP

🏆 Recommendation


Option 1: Railway (Recommended for Quick Deployment)

✅ Advantages

📦 Prerequisites

# Install Railway CLI
npm install -g @railway/cli

# Login to Railway
railway login

🚀 Deployment Steps

Step 1: Create Backend Dockerfile

Create deployment/Dockerfile.backend:

# Backend API Dockerfile
FROM node:20-alpine

WORKDIR /app

# Install dependencies
COPY package*.json yarn.lock ./
RUN yarn install --frozen-lockfile --production=false

# Copy source
COPY . .

# Build backend API and its dependencies
RUN npx nx build backend-api --configuration=production
RUN npx nx build api-contracts --configuration=production
RUN npx nx build backend-core --configuration=production

# Install only production dependencies
RUN yarn install --frozen-lockfile --production && yarn cache clean

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api || exit 1

# Start backend
CMD ["node", "dist/apis/backend-api/main.js"]

Step 2: Create Railway Configuration

Create railway.backend.json:

{
  "build": {
    "builder": "DOCKERFILE",
    "dockerfilePath": "deployment/Dockerfile.backend"
  },
  "deploy": {
    "healthcheckPath": "/api",
    "healthcheckTimeout": 300,
    "restartPolicyType": "ON_FAILURE",
    "restartPolicyMaxRetries": 10
  }
}

Step 3: Deploy to Railway

# Option A: Deploy via Railway CLI
cd /path/to/editor
railway up --service backend-api

# Option B: Deploy via GitHub Integration (Recommended)
# 1. Go to Railway Dashboard: https://railway.app/dashboard
# 2. Click "New Project"
# 3. Select "Deploy from GitHub repo"
# 4. Choose your repository
# 5. Select branch: ferrari-2 (or main)
# 6. Set build configuration:
#    - Root directory: /
#    - Dockerfile path: deployment/Dockerfile.backend
#    - Build command: (leave empty, Dockerfile handles it)
#    - Start command: node dist/apis/backend-api/main.js

Step 4: Configure Environment Variables in Railway

In Railway Dashboard > Project > Variables:

# MongoDB
MONGODB_CONNECTION_STRING=PASTE_YOUR_MONGODB_CONNECTION_STRING_HERE
MONGODB_DATABASE=gograb-api

# AI API Keys
OPENAI_API_KEY=PASTE_YOUR_OPENAI_API_KEY_HERE
ANTHROPIC_API_KEY=PASTE_YOUR_ANTHROPIC_API_KEY_HERE
GOOGLE_API_KEY=PASTE_YOUR_GOOGLE_API_KEY_HERE

# JWT Configuration
JWT_SECRET=JWT_SECRET_HERE
JWT_EXPIRATION=7d

# Server Configuration
PORT=${{PORT}}
NODE_ENV=production

# CORS Configuration (Update with your actual frontend URLs)
ALLOWED_ORIGINS=https://your-frontend-domain.com,https://gograb.space

Step 5: Get Your Backend URL

After deployment, Railway will provide a URL like:

https://backend-api-production-xxxx.up.railway.app

Step 6: Update Frontend Configuration

Update your frontend environment files to use the Railway backend:

gograb-space/src/environments/environment.prod.ts:

export const environment = {
  production: true,
  backendApiUrl: 'https://backend-api-production-xxxx.up.railway.app/api',
  // ... other config
};

Update all backend service URLs:

// libs/gograb-ai/src/lib/services/openai-proxy.service.ts
private readonly backendUrl = environment.production 
  ? environment.backendApiUrl
  : 'http://localhost:3000/api';

// apps/gograb-space/src/app/demos/storage-demo/services/mongodb-backend.service.ts
private readonly backendUrl = environment.production 
  ? environment.backendApiUrl
  : 'http://localhost:3000/api';

Step 7: Test Deployment

# Test health endpoint
curl https://backend-api-production-xxxx.up.railway.app/api

# Test authentication
curl -X POST https://backend-api-production-xxxx.up.railway.app/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"Test123!","name":"Test User"}'

# Test MongoDB connection
curl -X POST https://backend-api-production-xxxx.up.railway.app/api/storage/mongodb/test \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{}'

💰 Railway Cost Estimate

Basic Plan ($5/mo):
- 500 hours of usage
- $0.000463/hour after
- Perfect for MVP/Development

Pro Plan ($20/mo):
- Unlimited projects
- Priority support
- Better resources
- Production-ready

Typical Monthly Cost:
- Small API (< 10k requests/day): $5-10/mo
- Medium API (10k-100k requests/day): $20-50/mo
- Large API (100k+ requests/day): $50-200/mo

Option 2: Google Cloud Run (Best for Production Scale)

✅ Advantages

📦 Prerequisites

# Install Google Cloud SDK
# macOS
brew install --cask google-cloud-sdk

# Login
gcloud auth login
gcloud config set project your-project-id

🚀 Deployment Steps

Step 1: Create Cloud Run Dockerfile

Create deployment/Dockerfile.cloudrun:

# Cloud Run optimized Dockerfile
FROM node:20-alpine AS builder

WORKDIR /app

# Install dependencies
COPY package*.json yarn.lock ./
RUN yarn install --frozen-lockfile

# Copy source
COPY . .

# Build backend and dependencies
RUN npx nx build backend-api --configuration=production
RUN npx nx build api-contracts --configuration=production
RUN npx nx build backend-core --configuration=production

# Production stage
FROM node:20-alpine

WORKDIR /app

# Copy built artifacts
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

# Cloud Run requires PORT environment variable
ENV PORT=8080

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/api || exit 1

# Start backend
CMD ["node", "dist/apis/backend-api/main.js"]

Step 2: Build and Push to Google Container Registry

# Set your project ID
export PROJECT_ID=your-gcp-project-id
export REGION=us-central1
export SERVICE_NAME=backend-api

# Build and push to GCR
gcloud builds submit \
  --tag gcr.io/$PROJECT_ID/$SERVICE_NAME \
  --dockerfile deployment/Dockerfile.cloudrun

# Or use Cloud Build with config
gcloud builds submit --config cloudbuild.backend.yaml

Step 3: Create Cloud Build Configuration

Create cloudbuild.backend.yaml:

steps:
  # Build the container image
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - 'gcr.io/$PROJECT_ID/backend-api:$COMMIT_SHA'
      - '-t'
      - 'gcr.io/$PROJECT_ID/backend-api:latest'
      - '-f'
      - 'deployment/Dockerfile.cloudrun'
      - '.'

  # Push to Container Registry
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'push'
      - 'gcr.io/$PROJECT_ID/backend-api:$COMMIT_SHA'

  # Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'backend-api'
      - '--image'
      - 'gcr.io/$PROJECT_ID/backend-api:$COMMIT_SHA'
      - '--region'
      - 'us-central1'
      - '--platform'
      - 'managed'
      - '--allow-unauthenticated'
      - '--memory'
      - '512Mi'
      - '--cpu'
      - '1'
      - '--max-instances'
      - '100'
      - '--min-instances'
      - '0'
      - '--timeout'
      - '300s'

images:
  - 'gcr.io/$PROJECT_ID/backend-api:$COMMIT_SHA'
  - 'gcr.io/$PROJECT_ID/backend-api:latest'

options:
  machineType: 'N1_HIGHCPU_8'
  logging: CLOUD_LOGGING_ONLY

Step 4: Deploy to Cloud Run (CURRENTLY NOT USING - We are using Railway for now)

# Deploy manually
gcloud run deploy backend-api \
  --image gcr.io/$PROJECT_ID/backend-api:latest \
  --region us-central1 \
  --platform managed \
  --allow-unauthenticated \
  --memory 512Mi \
  --cpu 1 \
  --max-instances 100 \
  --min-instances 0 \
  --timeout 300s \
  --set-env-vars "NODE_ENV=production" \
  --set-secrets "MONGODB_CONNECTION_STRING=mongodb-connection-string:latest" \
  --set-secrets "JWT_SECRET=jwt-secret:latest" \
  --set-secrets "OPENAI_API_KEY=openai-api-key:latest" \
  --set-secrets "ANTHROPIC_API_KEY=anthropic-api-key:latest" \
  --set-secrets "GOOGLE_API_KEY=google-api-key:latest"

Step 5: Configure Secrets in Google Secret Manager

# Create secrets
echo -n "YOUR_MONGODB_CONNECTION_STRING_HERE" | \
  gcloud secrets create mongodb-connection-string --data-file=-

echo -n "YOUR_JWT_SECRET_HERE" | gcloud secrets create jwt-secret --data-file=-
echo -n "YOUR_OPENAI_API_KEY_HERE" | gcloud secrets create openai-api-key --data-file=-
echo -n "YOUR_ANTHROPIC_API_KEY_HERE" | gcloud secrets create anthropic-api-key --data-file=-
echo -n "YOUR_GOOGLE_API_KEY_HERE" | gcloud secrets create google-api-key --data-file=-

# Grant Cloud Run access to secrets
gcloud secrets add-iam-policy-binding mongodb-connection-string \
  --member="serviceAccount:[email protected]" \
  --role="roles/secretmanager.secretAccessor"

# Repeat for other secrets...

Step 6: Set Up Custom Domain (Optional)

# Map custom domain
gcloud run services add-iam-policy-binding backend-api \
  --region=us-central1 \
  --member="allUsers" \
  --role="roles/run.invoker"

# Map domain in Cloud Run Console
# https://console.cloud.google.com/run
# Select service > "Manage Custom Domains"

Step 7: Set Up CI/CD with GitHub Actions

Create .github/workflows/deploy-backend.yml:

name: Deploy Backend API to Cloud Run

on:
  push:
    branches:
      - main
      - ferrari-2
    paths:
      - 'apis/backend-api/**'
      - 'libs/api-contracts/**'
      - 'libs/backend-core/**'
      - 'deployment/Dockerfile.cloudrun'

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v1
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY }}

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v1

      - name: Build and push to GCR
        run: |
          gcloud builds submit \
            --tag gcr.io/${{ secrets.GCP_PROJECT_ID }}/backend-api:${{ github.sha }} \
            --dockerfile deployment/Dockerfile.cloudrun

      - name: Deploy to Cloud Run
        run: |
          gcloud run deploy backend-api \
            --image gcr.io/${{ secrets.GCP_PROJECT_ID }}/backend-api:${{ github.sha }} \
            --region us-central1 \
            --platform managed \
            --allow-unauthenticated

💰 Cloud Run Cost Estimate

Pricing Model: Pay-per-use

CPU: $0.00002400 per vCPU-second
Memory: $0.00000250 per GiB-second
Requests: $0.40 per million requests

Example Costs:

Small API (1,000 requests/day):
- 30,000 requests/month
- ~1 minute total compute time
- Cost: ~$0.01-0.50/mo

Medium API (10,000 requests/day):
- 300,000 requests/month
- ~10 minutes total compute time
- Cost: ~$5-15/mo

Large API (100,000 requests/day):
- 3,000,000 requests/month
- ~100 minutes total compute time
- Cost: ~$50-150/mo

Free Tier:
- 2 million requests/month
- 360,000 vCPU-seconds/month
- 180,000 GiB-seconds/month
- Perfect for starting out!

Option 3: Google App Engine

✅ Advantages

📦 Deployment Steps

Step 1: Create app.backend.yaml

runtime: nodejs20
service: backend-api
env: standard
instance_class: F1

automatic_scaling:
  min_instances: 0
  max_instances: 10
  target_cpu_utilization: 0.65
  target_throughput_utilization: 0.75

env_variables:
  NODE_ENV: 'production'
  PORT: '8080'
  MONGODB_DATABASE: 'gograb-api'

# Environment variables are set via Google Cloud Console or gcloud

Step 2: Deploy

# Deploy to App Engine
gcloud app deploy app.backend.yaml

# View logs
gcloud app logs tail -s backend-api

🔐 Environment Variables Setup

Required Variables

# MongoDB
MONGODB_CONNECTION_STRING=<your-connection-string>
MONGODB_DATABASE=gograb-api

# AI API Keys
OPENAI_API_KEY=<your-key>
ANTHROPIC_API_KEY=<your-key>
GOOGLE_API_KEY=<your-key>

# JWT
JWT_SECRET=<generate-with: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))">
JWT_EXPIRATION=7d

# Server
PORT=3000 (or $PORT for cloud platforms)
NODE_ENV=production

# CORS
ALLOWED_ORIGINS=https://your-frontend.com,https://app.gograb.space

Security Best Practices

  1. Never commit secrets to Git

  2. Use environment-specific secret managers:

    • Railway: Built-in secrets
    • Cloud Run: Google Secret Manager
    • App Engine: Secret Manager or environment variables
  3. Rotate keys regularly:

    # Generate new JWT secret
    node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
    
  4. Use different keys for dev/staging/production


✅ Pre-Deployment Checklist

Code Readiness

Infrastructure Readiness

Configuration Files

Testing

# Build locally to ensure it works
npx nx build backend-api --configuration=production

# Test the built output
node dist/apis/backend-api/main.js

# Test with Docker locally
docker build -f deployment/Dockerfile.backend -t backend-api-test .
docker run -p 3000:3000 \
  -e MONGODB_CONNECTION_STRING="..." \
  -e JWT_SECRET="..." \
  backend-api-test

# Test health endpoint
curl http://localhost:3000/api

🚀 Post-Deployment Configuration

1. Update Frontend to Use Production Backend

Update all service files:

// Create environment config
// apps/gograb-space/src/environments/environment.prod.ts
export const environment = {
  production: true,
  backendApiUrl: 'https://backend-api.your-domain.com/api',
  // Or Railway: 'https://backend-api-production-xxxx.up.railway.app/api'
  // Or Cloud Run: 'https://backend-api-xxxxx-uc.a.run.app/api'
};

// Update services to use environment config
// libs/gograb-ai/src/lib/services/backend-auth-adapter.service.ts
import { environment } from '@env/environment';

private readonly backendUrl = environment.backendApiUrl;

// Do the same for:
// - openai-proxy.service.ts
// - mongodb-backend.service.ts
// - Any other service that calls the backend

2. Configure Custom Domain (Recommended)

For Railway:

  1. Go to Railway Dashboard > Project Settings > Domains
  2. Add custom domain: api.gograb.space
  3. Update DNS:
    Type: CNAME
    Name: api
    Value: backend-api-production-xxxx.up.railway.app
    

For Cloud Run:

  1. Go to Cloud Run Console > Service > "Manage Custom Domains"
  2. Add domain: api.gograb.space
  3. Update DNS as instructed by GCP

3. Set Up Monitoring

Railway:

Cloud Run:

# View logs
gcloud run services logs tail backend-api --region=us-central1

# Set up monitoring in Cloud Console
# https://console.cloud.google.com/monitoring

4. Test Production Deployment

# Test health
curl https://api.gograb.space/api

# Test registration
curl -X POST https://api.gograb.space/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"Test123!","name":"Test"}'

# Test MongoDB (requires auth token)
curl -X POST https://api.gograb.space/api/storage/mongodb/test \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{}'

# Test AI completion (requires auth token)
curl -X POST https://api.gograb.space/api/ai/openai/chat \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <TOKEN>" \
  -d '{"messages":[{"role":"user","content":"Hello"}],"model":"gpt-4o-mini","maxTokens":50}'

📊 Monitoring and Maintenance

Key Metrics to Monitor

  1. Response Time

    • Target: < 500ms for API calls
    • Target: < 2000ms for AI completions
  2. Error Rate

    • Target: < 1% of requests
  3. Uptime

    • Target: 99.9% (43 minutes downtime/month)
  4. Database Connections

    • Monitor active connections
    • Watch for connection leaks
  5. AI API Usage

    • Track token usage
    • Monitor costs
    • Watch for rate limits

Logging Strategy

Log Levels:

What to Log:

What NOT to Log:

Maintenance Tasks

Daily:

Weekly:

Monthly:


🔧 Troubleshooting

Common Issues

1. "Cannot connect to MongoDB"

# Check connection string format
# Ensure special characters are URL-encoded
# Verify IP whitelist includes 0.0.0.0/0 (or cloud provider IPs)
# Test connection locally first

# Test MongoDB connection
mongosh "mongodb+srv://user:[email protected]/"

2. "Authentication failed"

# Check JWT_SECRET is set
# Verify token expiration
# Check CORS configuration
# Verify frontend is sending correct headers

3. "AI API rate limit exceeded"

# Implement rate limiting on your end
# Cache common responses
# Use cheaper models (gpt-4o-mini instead of gpt-4o)
# Monitor usage in provider dashboards

4. "Cold start timeout"

For Cloud Run:

# Increase timeout
gcloud run services update backend-api \
  --timeout 300s \
  --region us-central1

# Add minimum instances to prevent cold starts
gcloud run services update backend-api \
  --min-instances 1 \
  --region us-central1

For Railway:

5. "Build fails in Docker"

# Test build locally first
docker build -f deployment/Dockerfile.backend -t backend-test .

# Check logs for specific error
# Common issues:
# - Missing dependencies in package.json
# - TypeScript errors
# - Out of memory (increase Docker memory)

Debug Checklist

When something goes wrong:

  1. Check the logs

    # Railway
    railway logs --service backend-api
    
    # Cloud Run
    gcloud run services logs tail backend-api
    
  2. Verify environment variables

    # Railway
    railway variables --service backend-api
    
    # Cloud Run
    gcloud run services describe backend-api
    
  3. Test endpoints individually

    curl https://api.example.com/api
    curl https://api.example.com/api/auth/register -X POST -H "Content-Type: application/json" -d '{...}'
    
  4. Check MongoDB Atlas

    • Go to MongoDB Atlas Dashboard
    • Check "Network Access" (IP whitelist)
    • Check "Database Access" (users)
    • View "Metrics" for connection issues
  5. Check AI Provider Status


📞 Support Resources

Documentation

Community

Pricing Calculators


🎯 Quick Reference

Deploy Commands

# Railway
railway up --service backend-api

# Cloud Run
gcloud run deploy backend-api --image gcr.io/PROJECT/backend-api

# App Engine
gcloud app deploy app.backend.yaml

View Logs

# Railway
railway logs --service backend-api

# Cloud Run
gcloud run services logs tail backend-api

# App Engine
gcloud app logs tail -s backend-api

Update Environment Variables

# Railway (via CLI)
railway variables set KEY=value --service backend-api

# Cloud Run
gcloud run services update backend-api \
  --set-env-vars KEY=value

# App Engine
# Update app.backend.yaml and redeploy

✅ Deployment Complete!

Your backend API should now be deployed and accessible at:

Next steps:

  1. Update frontend to use production backend URL
  2. Test all endpoints from frontend
  3. Set up monitoring and alerts
  4. Document any custom configuration
  5. Train team on maintenance procedures

Need Help? Check the Troubleshooting section or reach out to the team!