Overview
This guide covers deploying Tambo360 to production, including platform-specific instructions, database setup, environment configuration, and best practices for a secure and scalable deployment.
Always test your deployment in a staging environment before deploying to production.
Pre-Deployment Checklist
Before deploying to production, ensure you have:
Environment Configuration
Deployment Architecture
Docker Self-hosted with full control
Railway Easy deployment with PostgreSQL
Render Automatic deploys from GitHub
AWS Scalable cloud infrastructure
DigitalOcean Droplets with App Platform
Vercel + Railway Frontend on Vercel, Backend on Railway
Docker Production Deployment
Build Production Images
Prepare environment
Create production environment file: NODE_ENV = production
PORT = 3000
DATABASE_URL = postgresql://user:password@db-host:5432/tambo? sslmode = require
JWT_SECRET = your-production-secret-min-32-chars
FRONTEND_URL = https://app.tambo360.com
BACKEND_URL = https://api.tambo360.com
EMAIL_USER = [email protected]
SENDGRID_API_KEY = SG.xxxxxxxxxxxxx
Build backend image
cd apps/backend
docker build --target production -t tambo360-backend:latest .
Build frontend image
cd apps/frontend
docker build --target production -t tambo360-frontend:latest .
Run production stack
# Using docker-compose
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Run database migrations
docker compose exec backend npx prisma migrate deploy
Production Docker Compose
Create docker-compose.prod.yml:
version : '3.8'
services :
backend :
build :
context : ./apps/backend
target : production
restart : always
environment :
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
- JWT_SECRET=${JWT_SECRET}
healthcheck :
test : [ "CMD" , "node" , "-e" , "require('http').get('http://localhost:3000/api/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })" ]
interval : 30s
timeout : 10s
retries : 3
start_period : 40s
frontend :
build :
context : ./apps/frontend
target : production
restart : always
ports :
- "80:80"
- "443:443"
volumes :
- ./ssl:/etc/nginx/ssl:ro
depends_on :
backend :
condition : service_healthy
Railway Deployment
Railway provides easy deployment with built-in PostgreSQL.
Install Railway CLI
npm install -g @railway/cli
railway login
Add PostgreSQL database
Railway automatically sets DATABASE_URL.
Configure backend service
Create railway.json in apps/backend: {
"build" : {
"builder" : "dockerfile" ,
"dockerfilePath" : "Dockerfile"
},
"deploy" : {
"startCommand" : "node dist/server.js" ,
"restartPolicyType" : "on_failure"
}
}
Set environment variables
railway variables set JWT_SECRET=your-secret-key
railway variables set FRONTEND_URL=https://your-app.railway.app
railway variables set NODE_ENV=production
Run migrations
railway run npx prisma migrate deploy
Railway provides automatic HTTPS and custom domains.
Render Deployment
Backend on Render
Connect GitHub repository
Go to Render Dashboard
Click “New +” → “Web Service”
Connect your GitHub repository
Configure service
Name: tambo360-backend
Environment: Docker
Dockerfile Path: apps/backend/Dockerfile
Docker Context Directory: apps/backend
Add environment variables
NODE_ENV = production
DATABASE_URL =< from-render-postgresql >
JWT_SECRET =< your-secret >
FRONTEND_URL = https://tambo360.onrender.com
Add PostgreSQL database
Click “New +” → “PostgreSQL”
Copy the Internal Database URL
Add to backend environment variables
Deploy
Render automatically deploys on git push.
Frontend on Render
Create static site
Click “New +” → “Static Site”
Connect repository
Configure build
Build Command: cd apps/frontend && npm install && npm run build
Publish Directory: apps/frontend/dist
Add environment variables
VITE_API_URL = https://tambo360-backend.onrender.com/api
Vercel + Railway
Deploy frontend on Vercel and backend on Railway for optimal performance.
Frontend on Vercel
Install Vercel CLI
npm install -g vercel
vercel login
Configure project
Create vercel.json in apps/frontend: {
"buildCommand" : "npm run build" ,
"outputDirectory" : "dist" ,
"framework" : "vite" ,
"rewrites" : [
{ "source" : "/(.*)" , "destination" : "/" }
]
}
Set environment variables
vercel env add VITE_API_URL production
# Enter: https://your-backend.railway.app/api
Deploy
cd apps/frontend
vercel --prod
Backend on Railway
Follow the Railway deployment steps above for the backend.
AWS Deployment
Deploy using AWS ECS (Elastic Container Service) and RDS (PostgreSQL).
Prerequisites
AWS Account
AWS CLI installed
Docker images pushed to ECR
Architecture
Frontend: S3 + CloudFront
Backend: ECS Fargate
Database: RDS PostgreSQL
Secrets: AWS Secrets Manager
Create RDS PostgreSQL instance
aws rds create-db-instance \
--db-instance-identifier tambo360-db \
--db-instance-class db.t3.micro \
--engine postgres \
--engine-version 15.3 \
--master-username postgres \
--master-user-password < secure-passwor d > \
--allocated-storage 20
Push Docker images to ECR
# Create ECR repository
aws ecr create-repository --repository-name tambo360-backend
# Build and push
docker build -t tambo360-backend ./apps/backend
docker tag tambo360-backend:latest < account-i d > .dkr.ecr. < regio n > .amazonaws.com/tambo360-backend:latest
docker push < account-i d > .dkr.ecr. < regio n > .amazonaws.com/tambo360-backend:latest
Create ECS cluster and service
Use AWS Console or Terraform to create:
ECS Cluster
Task Definition (with environment variables)
ECS Service with Load Balancer
Deploy frontend to S3
cd apps/frontend
npm run build
aws s3 sync dist/ s3://tambo360-frontend
# Configure CloudFront distribution
aws cloudfront create-distribution --origin-domain-name tambo360-frontend.s3.amazonaws.com
SSL/TLS Configuration
Using Let’s Encrypt with Nginx
Install Certbot
sudo apt install certbot python3-certbot-nginx
Obtain SSL certificate
sudo certbot --nginx -d api.tambo360.com -d app.tambo360.com
Auto-renewal
# Test renewal
sudo certbot renew --dry-run
# Certbot creates a cron job automatically
Database Migrations in Production
Always backup your database before running migrations in production.
# 1. Backup database
pg_dump -U postgres -h db-host -d tambo > backup_ $( date +%Y%m%d ) .sql
# 2. Test migration in staging
pnpm prisma migrate deploy --preview-feature
# 3. Apply to production
pnpm prisma migrate deploy
# 4. Verify
pnpm prisma migrate status
Monitoring and Logging
Health Check Endpoint
The backend includes a health check at /api/health:
app . get ( '/api/health' , ( req , res ) => {
res . status ( 200 ). json ({ status: 'healthy' , timestamp: new Date () });
});
Setup Monitoring
PM2
Docker Logs
Cloud Monitoring
# Install PM2
npm install -g pm2
# Start backend with PM2
pm2 start dist/server.js --name tambo360-backend
# Monitor
pm2 monit
# View logs
pm2 logs
# View logs
docker compose logs -f backend
# Export logs
docker compose logs backend > backend.log
AWS: CloudWatch Logs
Railway: Built-in logs dashboard
Render: Logs in service dashboard
Enable Gzip Nginx configuration: gzip on ;
gzip_types text/plain text/css application/json;
Database Connection Pooling Configure in DATABASE_URL: ?connection_limit=10&pool_timeout=10
CDN for Static Assets Use CloudFront, Cloudflare, or Vercel Edge Network
Redis Caching Cache frequently accessed data: docker run -d --name redis -p 6379:6379 redis:7
Backup Strategy
Automated Database Backups
#!/bin/bash
# Database backup script
BACKUP_DIR = "/backups/tambo360"
DATE = $( date +%Y%m%d_%H%M%S )
BACKUP_FILE = " $BACKUP_DIR /tambo_ $DATE .sql"
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup database
pg_dump $DATABASE_URL > $BACKUP_FILE
# Compress
gzip $BACKUP_FILE
# Upload to S3 (optional)
aws s3 cp $BACKUP_FILE .gz s3://tambo360-backups/
# Delete backups older than 30 days
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
echo "Backup completed: $BACKUP_FILE .gz"
Schedule with cron:
# Run daily at 2 AM
0 2 * * * /usr/local/bin/backup.sh
Rollback Strategy
Keep previous Docker images
docker tag tambo360-backend:latest tambo360-backend:previous
Rollback deployment
docker compose down
docker tag tambo360-backend:previous tambo360-backend:latest
docker compose up -d
Rollback database migrations
# Restore from backup
psql $DATABASE_URL < backup_20260308.sql
Security Hardening
Secure Environment Variables
Use AWS Secrets Manager, HashiCorp Vault, or Railway secrets
Rotate secrets regularly
Never log sensitive values
server {
listen 80 ;
return 301 https://$ host $ request_uri ;
}
Use express-rate-limit: import rateLimit from 'express-rate-limit' ;
const limiter = rateLimit ({
windowMs: 15 * 60 * 1000 ,
max: 100
});
app . use ( '/api' , limiter );
CI/CD Pipeline
GitHub Actions Example
.github/workflows/deploy.yml
name : Deploy to Production
on :
push :
branches : [ main ]
jobs :
deploy :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v3
- name : Build Docker images
run : |
docker build -t tambo360-backend ./apps/backend
docker build -t tambo360-frontend ./apps/frontend
- name : Run tests
run : |
cd apps/backend && npm test
cd apps/frontend && npm test
- name : Deploy to Railway
env :
RAILWAY_TOKEN : ${{ secrets.RAILWAY_TOKEN }}
run : |
npm install -g @railway/cli
railway up
- name : Run migrations
run : railway run npx prisma migrate deploy
Troubleshooting
Check backend health: curl http://localhost:3000/api/health
docker compose logs backend
Database connection timeout
Check DATABASE_URL is correct
Verify database is accepting connections
Check firewall rules
Increase connection timeout in DATABASE_URL
CORS errors in production
Update CORS_ORIGIN to match production frontend URL: CORS_ORIGIN = https://app.tambo360.com
Post-Deployment
Monitor metrics
Response times
Error rates
Database query performance
Memory/CPU usage
Setup alerts
Configure alerts for:
Application downtime
High error rates
Database connection failures
Disk space warnings
Next Steps
Monitoring Guide Set up comprehensive monitoring
API Reference Explore available endpoints