Skip to main content

Overview

This guide covers deploying the Los Inmaduros Backend to production environments. The application is Docker-ready and can be deployed to any platform that supports Node.js or containers.

Before You Deploy

Set all required environment variables in your deployment platform. See Environment Variables for details.Required variables:
  • NODE_ENV=production
  • DATABASE_URL
  • CLERK_SECRET_KEY (use sk_live_... for production)
  • CLERK_PUBLISHABLE_KEY (use pk_live_... for production)
  • SUPABASE_URL
  • SUPABASE_ANON_KEY
  • FRONTEND_URL (your production frontend URL)
You’ll need a production PostgreSQL database. Options include:
  • Render PostgreSQL (free tier available)
  • Supabase Database (generous free tier)
  • Railway PostgreSQL
  • AWS RDS
  • Google Cloud SQL
  1. Go to Clerk Dashboard
  2. Switch to your production instance or create one
  3. Copy your production keys (sk_live_... and pk_live_...)
  4. Configure your production domain in Clerk settings
  1. Create a production project in Supabase
  2. Create a storage bucket for photos
  3. Configure bucket policies for public access
  4. Copy your production URL and anon key
Render offers a free tier with automatic Docker deployments and managed PostgreSQL.
1

Create a new Web Service

  1. Go to Render Dashboard
  2. Click “New” → “Web Service”
  3. Connect your GitHub repository
  4. Render automatically detects the Dockerfile
2

Configure the service

  • Name: los-inmaduros-backend
  • Environment: Docker
  • Region: Choose closest to your users
  • Instance Type: Free tier or Starter ($7/month)
3

Add environment variables

Go to “Environment” tab and add:
NODE_ENV=production
FRONTEND_URL=https://your-frontend.vercel.app
CLERK_SECRET_KEY=sk_live_...
CLERK_PUBLISHABLE_KEY=pk_live_...
SUPABASE_URL=https://xxxxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
4

Create PostgreSQL database

  1. In Render Dashboard, click “New” → “PostgreSQL”
  2. Choose free tier or paid
  3. Copy the “Internal Database URL”
  4. Add to your web service environment variables:
DATABASE_URL=postgresql://...
5

Deploy

Click “Create Web Service”. Render will:
  • Build your Docker image
  • Run database migrations automatically
  • Deploy and start your service
Your API will be available at https://your-service.onrender.com

Railway

Railway provides a simple deployment experience with automatic scaling.
1

Create new project

  1. Go to Railway
  2. Click “New Project” → “Deploy from GitHub repo”
  3. Select your repository
2

Add PostgreSQL

  1. Click “New” → “Database” → “Add PostgreSQL”
  2. Railway generates DATABASE_URL automatically
  3. No manual configuration needed
3

Configure environment variables

  1. Click on your service → “Variables”
  2. Add all required variables
  3. Use “Raw Editor” for bulk import:
NODE_ENV=production
FRONTEND_URL=https://your-frontend.vercel.app
CLERK_SECRET_KEY=sk_live_...
CLERK_PUBLISHABLE_KEY=pk_live_...
SUPABASE_URL=https://xxxxx.supabase.co
SUPABASE_ANON_KEY=eyJ...
4

Deploy

Railway automatically deploys on push to your main branch.Your API will be available at https://your-app.up.railway.app

Fly.io

Fly.io runs your app close to users with global distribution.
1

Install Fly CLI

curl -L https://fly.io/install.sh | sh
2

Launch your app

# Login to Fly.io
fly auth login

# Launch (creates fly.toml)
fly launch
Fly detects your Dockerfile automatically.
3

Create PostgreSQL database

fly postgres create
fly postgres attach my-postgres-db
This sets DATABASE_URL automatically.
4

Set environment variables

fly secrets set NODE_ENV=production
fly secrets set FRONTEND_URL=https://your-frontend.vercel.app
fly secrets set CLERK_SECRET_KEY=sk_live_...
fly secrets set CLERK_PUBLISHABLE_KEY=pk_live_...
fly secrets set SUPABASE_URL=https://xxxxx.supabase.co
fly secrets set SUPABASE_ANON_KEY=eyJ...
5

Deploy

fly deploy
Your API will be available at https://your-app.fly.dev

Docker Production Deployment

If deploying to a platform that supports Docker Compose:
# Use production Docker Compose configuration
docker-compose -f docker-compose.prod.yml up -d

Production Docker Compose

The docker-compose.prod.yml includes:
  • Multi-stage Dockerfile build for smaller images
  • Production-only dependencies
  • Optimized restart policies
  • Environment variable placeholders
  • Automatic migrations on startup
services:
  backend:
    build:
      target: production
    restart: always
    environment:
      NODE_ENV: production
    command: sh -c "npx prisma migrate deploy && npm start"
See Docker Deployment for more details.

Database Migrations

Migrations run automatically on startup via the Docker command:
npx prisma migrate deploy && npm start

Manual Migration

If you need to run migrations manually:
# On Render or Railway
npx prisma migrate deploy

# With Docker
docker-compose exec backend npx prisma migrate deploy

# On Fly.io
fly ssh console
npx prisma migrate deploy

Security Best Practices

Critical security considerations for production:

Environment Variables

  • Use production Clerk keys (sk_live_..., pk_live_...)
  • Never commit .env files to version control
  • Use platform-provided secrets management
  • Rotate credentials regularly

CORS Configuration

# Specific frontend URL only
FRONTEND_URL=https://your-exact-frontend.vercel.app

# NEVER use wildcards in production
# FRONTEND_URL=* ❌

Rate Limiting

The backend includes built-in rate limiting:
  • General requests: 100 requests / 15 minutes per IP
  • Authentication: 5 requests / 15 minutes per IP
  • Resource creation: 20 requests / 15 minutes per IP
Configured in src/shared/middlewares/rate-limit.middleware.ts.

File Upload Security

  • 5MB maximum file size
  • Allowed formats: JPEG, PNG, GIF, WebP only
  • Filename sanitization (prevents path traversal)
  • MIME type validation

Database Security

  • Use strong, randomly generated passwords
  • Enable SSL connections (?sslmode=require)
  • Regular backups (most platforms do this automatically)
  • Limit database user permissions

HTTPS

All recommended platforms (Render, Railway, Fly.io) provide automatic HTTPS with Let’s Encrypt certificates.

Performance Optimization

Database Connection Pooling

Prisma handles connection pooling automatically. For high-traffic applications:
# Add connection pool settings to DATABASE_URL
DATABASE_URL=postgresql://user:pass@host:5432/db?connection_limit=10&pool_timeout=20

Caching

Consider adding Redis for caching frequently accessed data:
  • Route listings
  • User profiles
  • Meetup data

CDN for Images

Supabase Storage includes built-in CDN. Enable image transformations:
const imageUrl = `${SUPABASE_URL}/storage/v1/object/public/photos/${filename}?width=800&quality=80`

Monitoring and Logging

Error Tracking

Consider integrating:
  • Sentry for error tracking
  • LogRocket for session replay
  • Platform-native logging (Render Logs, Railway Logs, etc.)

Health Checks

Most platforms support health check endpoints. The API root / returns:
{
  "message": "Los Inmaduros Backend API",
  "version": "1.0.0",
  "status": "healthy"
}

Uptime Monitoring

Use services like:

Post-Deployment Checklist

1

Verify API is running

curl https://your-api.onrender.com/
Should return healthy status.
2

Test authentication

Create a test account with Clerk and verify login works.
3

Check database connection

# View logs for "✅ Database connected successfully"
4

Test file uploads

Upload a test photo to verify Supabase Storage integration.
5

Verify CORS

Test API calls from your production frontend.
6

Set up monitoring

Configure error tracking and uptime monitoring.
7

Review API documentation

Your Swagger docs will be at https://your-api.com/api-docs

Troubleshooting

Application won’t start

Check logs for missing environment variables:
# Render
View logs in dashboard

# Railway
railway logs

# Fly.io
fly logs

Database connection failed

Verify DATABASE_URL format:
# Correct format
DATABASE_URL=postgresql://user:password@host:5432/database

# With SSL (recommended for production)
DATABASE_URL=postgresql://user:password@host:5432/database?sslmode=require

Migrations failing

Reset and redeploy:
# Reset database (⚠️ deletes all data)
prisma migrate reset

# Or run migrations manually
prisma migrate deploy

CORS errors from frontend

Ensure FRONTEND_URL exactly matches your frontend:
# Must match exactly
FRONTEND_URL=https://losinmaduros.vercel.app

# Not
FRONTEND_URL=https://losinmaduros.vercel.app/

Scaling Considerations

Horizontal Scaling

Most platforms support automatic scaling:
  • Render: Upgrade to Standard plan ($25/month) for auto-scaling
  • Railway: Automatic scaling based on load
  • Fly.io: fly scale count 2 to run 2 instances

Database Scaling

For high traffic:
  • Enable read replicas
  • Use connection pooling (PgBouncer)
  • Consider managed databases (AWS RDS, Google Cloud SQL)

Vertical Scaling

Increase instance resources:
  • Render: Upgrade to larger instance types
  • Railway: Automatically scales resources
  • Fly.io: Modify fly.toml VM size

Cost Estimates

Free Tier (Development/Testing)

  • Render: Free web service + free PostgreSQL
  • Railway: $5/month credit (enough for small apps)
  • Supabase: 500MB storage, 2GB bandwidth
  • Clerk: 10,000 monthly active users
Total: $0-5/month

Production (Low Traffic)

  • Render: Starter web service (7)+StarterPostgreSQL(7) + Starter PostgreSQL (7)
  • Supabase: Free tier sufficient
  • Clerk: Free tier sufficient
Total: ~$14/month

Production (Medium Traffic)

  • Render: Standard web service (25)+StandardPostgreSQL(25) + Standard PostgreSQL (20)
  • Supabase: Pro plan ($25)
  • Clerk: Pro plan ($25)
Total: ~$95/month

Next Steps

Environment Variables

Review all required environment variables

Docker Deployment

Learn about Docker configuration

API Reference

Explore the API endpoints

Authentication

Configure Clerk authentication

Build docs developers (and LLMs) love