This guide covers best practices and considerations for deploying the Horse Trust platform to production.
Pre-Deployment Checklist
Before deploying to production, ensure you have completed the following:
Security Audit
Environment variables are properly secured
JWT secrets are strong and unique
CORS origins are restricted to specific domains
Rate limiting is configured
Helmet.js security headers are enabled
Database Preparation
MongoDB production cluster is set up
Database backups are configured
Connection pooling is optimized
Database indexes are created
Code Quality
Linting errors are resolved
TypeScript compilation is successful
Dependencies are up to date
Performance
Build optimization is complete
API response times are acceptable
Socket.io performance is tested
Environment Configuration
Production Environment Variables
Never use development settings in production. Update all configuration values.
Server (Backend) Production .env
# ================================
# PRODUCTION SERVER CONFIGURATION
# ================================
PORT = 8031
NODE_ENV = production
# ================================
# DATABASE
# ================================
MONGO_URI = mongodb+srv://prod-user:[email protected] /horsetrust_prod? retryWrites = true & w = majority
# ================================
# AUTHENTICATION (Use strong secrets!)
# ================================
JWT_SECRET = GENERATE-STRONG-RANDOM-SECRET-KEY-HERE
JWT_EXPIRES_IN = 7d
BCRYPT_SALT_ROUNDS = 12
# ================================
# CORS (Specific domains only!)
# ================================
CORS_ORIGINS = https://horsetrust.com,https://www.horsetrust.com,https://app.horsetrust.com
Client (Frontend) Production .env.production
# ==========================================
# PRODUCTION CLIENT CONFIGURATION
# ==========================================
# API URL - Production backend
NEXT_PUBLIC_API_URL = https://api.horsetrust.com/api
# Cloudinary
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME = di2agiylz
NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET = horse_trust_uploads
Deployment Options
Option 1: Vercel (Frontend) + Railway/Render (Backend)
Recommended for easy deployment with minimal configuration.
Deploy Frontend to Vercel
Navigate to Client Directory
Deploy
Or connect your GitHub repository through the Vercel Dashboard :
Import your repository
Configure project settings:
Framework: Next.js
Root Directory: client
Build Command: npm run build
Output Directory: .next
Add environment variables in Vercel dashboard
Deploy
Configure Environment Variables
In Vercel dashboard, add:
NEXT_PUBLIC_API_URL
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME
NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET
Deploy Backend to Railway
Create New Project
Connect your GitHub repository
Select the server directory as root
Configure Build Settings
# railway.json (optional)
{
"build" : {
"builder" : "NIXPACKS" ,
"buildCommand" : "npm install && npm run build"
},
"deploy" : {
"startCommand" : "npm start" ,
"restartPolicyType" : "ON_FAILURE" ,
"restartPolicyMaxRetries" : 10
}
}
Add Environment Variables
In Railway dashboard, add all server environment variables:
PORT (Railway auto-provides this)
NODE_ENV=production
MONGO_URI
JWT_SECRET
JWT_EXPIRES_IN
BCRYPT_SALT_ROUNDS
CORS_ORIGINS
Deploy
Railway will automatically deploy on git push to main branch.
Option 2: Docker Deployment
For containerized deployments on any platform.
Server Dockerfile
# server/Dockerfile
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Production image
FROM node:24-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
EXPOSE 8031
CMD [ "npm" , "start" ]
Client Dockerfile
# client/Dockerfile
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production image
FROM node:24-alpine
WORKDIR /app
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
COPY --from=builder /app/public ./public
EXPOSE 8030
CMD [ "npm" , "start" ]
Docker Compose
# docker-compose.yml
version : '3.8'
services :
server :
build :
context : ./server
dockerfile : Dockerfile
ports :
- "8031:8031"
environment :
- NODE_ENV=production
- PORT=8031
- MONGO_URI=${MONGO_URI}
- JWT_SECRET=${JWT_SECRET}
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN}
- BCRYPT_SALT_ROUNDS=${BCRYPT_SALT_ROUNDS}
- CORS_ORIGINS=${CORS_ORIGINS}
restart : unless-stopped
healthcheck :
test : [ "CMD" , "curl" , "-f" , "http://localhost:8031/test" ]
interval : 30s
timeout : 10s
retries : 3
client :
build :
context : ./client
dockerfile : Dockerfile
ports :
- "8030:8030"
environment :
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
- NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=${NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME}
- NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET=${NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET}
depends_on :
- server
restart : unless-stopped
Deploy with Docker Compose:
# Build and start services
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop services
docker-compose down
Option 3: VPS Deployment (Ubuntu/Debian)
For deployment on a virtual private server.
Server Setup
# Update system
sudo apt update && sudo apt upgrade -y
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install -y nodejs
# Install PM2 (Process Manager)
sudo npm install -g pm2
# Install Nginx
sudo apt install -y nginx
Clone and Build
# Clone repository
git clone < your-repo-ur l > /var/www/horsetrust
cd /var/www/horsetrust
# Build server
cd server
npm install
npm run build
# Build client
cd ../client
npm install
npm run build
Configure PM2
Create ecosystem.config.js: module . exports = {
apps: [
{
name: 'horsetrust-server' ,
cwd: '/var/www/horsetrust/server' ,
script: 'npm' ,
args: 'start' ,
env: {
NODE_ENV: 'production' ,
PORT: 8031
}
},
{
name: 'horsetrust-client' ,
cwd: '/var/www/horsetrust/client' ,
script: 'npm' ,
args: 'start' ,
env: {
NODE_ENV: 'production'
}
}
]
};
Start applications: pm2 start ecosystem.config.js
pm2 save
pm2 startup
Configure Nginx
Create /etc/nginx/sites-available/horsetrust: # Backend API
server {
listen 80 ;
server_name api.horsetrust.com;
location / {
proxy_pass http://localhost:8031;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection 'upgrade' ;
proxy_set_header Host $ host ;
proxy_cache_bypass $ http_upgrade ;
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
}
# WebSocket support
location /socket.io/ {
proxy_pass http://localhost:8031;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection "upgrade" ;
}
}
# Frontend
server {
listen 80 ;
server_name horsetrust.com www.horsetrust.com;
location / {
proxy_pass http://localhost:8030;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection 'upgrade' ;
proxy_set_header Host $ host ;
proxy_cache_bypass $ http_upgrade ;
}
}
Enable and restart: sudo ln -s /etc/nginx/sites-available/horsetrust /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Set Up SSL with Let's Encrypt
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d horsetrust.com -d www.horsetrust.com -d api.horsetrust.com
Production Considerations
Security
Strong Secrets Use cryptographically secure random strings for JWT_SECRET:
CORS Restriction Never use CORS_ORIGINS=* in production. Specify exact domains.
HTTPS Only Always use SSL/TLS certificates. Use Let’s Encrypt for free certificates.
Rate Limiting The server includes express-rate-limit - ensure it’s properly configured.
Database
Production Database Checklist:
Use MongoDB Atlas production tier with automated backups
Configure proper network security (IP whitelist)
Enable database auditing and monitoring
Set up connection pooling
Create appropriate indexes for queries
Implement backup and disaster recovery procedures
Server Optimization:
// Mongoose connection with production settings
mongoose . connect ( uri , {
serverSelectionTimeoutMS: 5000 ,
socketTimeoutMS: 45000 ,
maxPoolSize: 10 , // Add connection pooling
minPoolSize: 5
});
Next.js Optimization:
// next.config.js
module . exports = {
compress: true ,
poweredByHeader: false ,
generateEtags: true ,
images: {
domains: [ 'res.cloudinary.com' ],
formats: [ 'image/avif' , 'image/webp' ]
}
};
Monitoring
Application Monitoring
Use PM2 monitoring or services like:
Datadog
New Relic
Sentry (error tracking)
Database Monitoring
MongoDB Atlas provides built-in monitoring:
Query performance
Connection metrics
Storage usage
Server Health Checks
Implement health check endpoints: app . get ( '/health' , ( req , res ) => {
res . json ({
status: 'healthy' ,
uptime: process . uptime (),
timestamp: Date . now ()
});
});
Logging
The server uses Morgan for HTTP logging. In production: // Use 'combined' format for detailed logs
app . use ( morgan ( 'combined' ));
Graceful Shutdown
The server already implements graceful shutdown:
process . on ( 'SIGTERM' , () => {
console . log ( 'SIGTERM received. Shutting down...' );
httpServer . close (() => process . exit ( 0 ));
});
This ensures:
Active connections are completed
Socket.io connections are closed properly
Database connections are released
Continuous Deployment
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 : Setup Node.js
uses : actions/setup-node@v3
with :
node-version : '24'
- name : Build Server
run : |
cd server
npm ci
npm run build
- name : Build Client
run : |
cd client
npm ci
npm run build
- name : Deploy
# Add your deployment commands here
run : echo "Deploy to your platform"
Troubleshooting Production Issues
Check for memory leaks with Node.js profiling
Ensure proper database connection pooling
Monitor Socket.io connections
Consider horizontal scaling
Add database indexes
Implement caching (Redis)
Optimize MongoDB queries
Use CDN for static assets
Enable gzip compression
Socket.io Connection Issues
Verify WebSocket support on your host
Check proxy configuration for WebSocket upgrades
Ensure sticky sessions for load balancers
Review CORS settings
Database Connection Errors
Verify MongoDB Atlas IP whitelist
Check connection string format
Monitor connection pool usage
Review MongoDB Atlas metrics
Rollback Strategy
In case of deployment issues:
# Using PM2
pm2 list
pm2 stop all
# Revert to previous git commit
git checkout < previous-commit-has h >
# Rebuild and restart
npm install
npm run build
pm2 restart all
Next Steps
Monitoring Setup Implement comprehensive monitoring and alerting
Backup Strategy Set up automated database backups and recovery procedures
Load Testing Perform load testing to identify bottlenecks
Documentation Document your deployment process and runbooks