Deployment Guide
Deploy ShopySeed to production with Docker, Vercel, AWS ECS, Kubernetes, and other cloud platforms.
This guide covers deploying ShopySeed to production environments, from simple Docker deployments to scalable cloud infrastructure.
Table of Contents
- Prerequisites
- Environment Configuration
- Docker Production Deployment
- Cloud Platform Deployments
- Database Setup
- Stripe Configuration
- Email Configuration
- Security & SSL
- Monitoring & Health Checks
- Backup & Recovery
- Performance Optimization
Prerequisites
Production Requirements
| Component | Minimum | Recommended | Notes |
|---|---|---|---|
| CPU | 1 vCPU | 2+ vCPUs | For API server |
| RAM | 1GB | 4GB+ | Node.js + PostgreSQL + Redis |
| Storage | 10GB | 50GB+ | Database, logs, uploads |
| Bandwidth | 100Mbps | 1Gbps | For user uploads/downloads |
Required Services
- PostgreSQL 16+: Primary database
- Redis 7+: Caching and session storage
- SMTP Service: Email delivery (Resend, SendGrid, etc.)
- Stripe Account: Payment processing
- Domain & SSL: HTTPS certificate
Environment Configuration
Production Environment Files
Create production environment configuration:
# Copy production templates
cp .env.production.example .env.production
# Configure API environment
cp apps/api/.env.production.example apps/api/.env.production
# Configure Web environment
cp apps/web/.env.production.example apps/web/.env.productionCore Environment Variables
API Configuration (apps/api/.env.production)
# === APPLICATION ===
NODE_ENV=production
PORT=3011
LOG_LEVEL=info
# === DATABASE ===
DATABASE_URL=postgresql://postgres:STRONG_PASSWORD@postgres:5432/shopyseed_prod?schema=public
POSTGRES_USER=postgres
POSTGRES_PASSWORD=STRONG_PASSWORD_HERE
POSTGRES_DB=shopyseed_prod
POSTGRES_PORT=5433
# === REDIS ===
REDIS_URL=redis://redis:6379
REDIS_PORT=6379
# === SECURITY ===
JWT_SECRET=GENERATE_STRONG_32_CHAR_SECRET_HERE
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
# === RATE LIMITING ===
RATE_LIMIT_TTL=60000
RATE_LIMIT_MAX=100
# === STRIPE ===
STRIPE_SECRET_KEY=sk_live_YOUR_LIVE_STRIPE_KEY
STRIPE_WEBHOOK_SECRET=whsec_YOUR_WEBHOOK_SECRET
# === EMAIL ===
EMAIL_HOST=smtp.sendgrid.net
EMAIL_PORT=587
EMAIL_USER=apikey
EMAIL_PASSWORD=YOUR_SENDGRID_API_KEY
EMAIL_FROM=noreply@yourdomain.com
# === OAUTH (Optional) ===
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secretWeb Configuration (apps/web/.env.production)
# === API CONNECTION ===
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
# === STRIPE ===
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_YOUR_LIVE_PUBLISHABLE_KEY
# === OAUTH URLS ===
NEXT_PUBLIC_GOOGLE_OAUTH_URL=https://api.yourdomain.com/auth/oauth/google
NEXT_PUBLIC_GITHUB_OAUTH_URL=https://api.yourdomain.com/auth/oauth/github
# === ANALYTICS (Optional) ===
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXXSecurity Best Practices
Generate Secure Secrets
# JWT Secret (minimum 32 characters)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Strong PostgreSQL password
openssl rand -base64 32
# Stripe webhook secret
# Get from Stripe Dashboard → Webhooks → Endpoint → Signing secretEnvironment Security Checklist
- All secrets are generated uniquely for production
- No development credentials are used
- Environment files are never committed to git
- Secrets are stored in secure secret management (AWS Secrets, etc.)
- CORS_ORIGINS only includes your production domains
- Rate limiting is appropriately configured for production load
Docker Production Deployment
Single-Server Docker Deployment
The simplest production deployment uses Docker Compose on a single server.
1. Prepare Server
# Update system
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Install Docker Compose
sudo apt install docker-compose-plugin -y
# Create application user
sudo useradd -m -s /bin/bash shopyseed
sudo usermod -aG docker shopyseed2. Deploy Application
# Clone repository
git clone https://github.com/yourusername/shopyseed.git /home/shopyseed/app
cd /home/shopyseed/app
# Setup environment
cp .env.production.example .env.production
cp apps/api/.env.production.example apps/api/.env.production
cp apps/web/.env.production.example apps/web/.env.production
# Edit environment files with production values
nano apps/api/.env.production
nano apps/web/.env.production
# Build and start services
docker compose -f docker-compose.prod.yml up -d --build
# Check services are running
docker compose -f docker-compose.prod.yml ps3. Database Migration
# Run database migrations
docker compose -f docker-compose.prod.yml exec api pnpm prisma migrate deploy
# (Optional) Seed production data
docker compose -f docker-compose.prod.yml exec api pnpm db:seed:prodDocker Services
The production Docker Compose includes:
# docker-compose.prod.yml (simplified)
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
api:
build:
context: .
dockerfile: apps/api/Dockerfile.prod
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- JWT_SECRET=${JWT_SECRET}
depends_on:
- postgres
- redis
web:
build:
context: .
dockerfile: apps/web/Dockerfile.prod
environment:
- NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
depends_on:
- api
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- certbot_certs:/etc/letsencrypt
depends_on:
- api
- webNginx Configuration
# nginx.conf
upstream api {
server api:3011;
}
upstream web {
server web:3000;
}
server {
listen 80;
server_name yourdomain.com www.yourdomain.com api.yourdomain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
location / {
proxy_pass http://web;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl http2;
server_name api.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
location / {
proxy_pass http://api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# API-specific settings
proxy_read_timeout 60s;
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
# Handle large uploads
client_max_body_size 100M;
}
}Cloud Platform Deployments
Vercel + PlanetScale + Redis Cloud
A popular serverless deployment option:
1. Deploy Web App to Vercel
# Install Vercel CLI
npm i -g vercel
# Deploy from apps/web directory
cd apps/web
vercel
# Configure environment variables in Vercel dashboard
# - NEXT_PUBLIC_API_URL
# - NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY2. Deploy API to Railway/Render
# Create Dockerfile for API
# apps/api/Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3011
CMD ["npm", "run", "start:prod"]3. Setup PlanetScale Database
# Install PlanetScale CLI
curl -fsSL https://get.planetscale.com/install.sh | bash
# Create database
pscale database create shopyseed-prod
# Get connection string
pscale connect shopyseed-prod main --port 3309
# Update DATABASE_URL in deployment environmentAWS ECS Deployment
For more control and scalability:
1. ECS Task Definition
{
"family": "shopyseed-api",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::account:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "api",
"image": "your-ecr-repo/shopyseed-api:latest",
"portMappings": [
{
"containerPort": 3011,
"protocol": "tcp"
}
],
"environment": [
{
"name": "NODE_ENV",
"value": "production"
}
],
"secrets": [
{
"name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:region:account:secret:shopyseed/database-url"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/shopyseed-api",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}Kubernetes Deployment
For large-scale deployments:
# k8s/api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: shopyseed-api
spec:
replicas: 3
selector:
matchLabels:
app: shopyseed-api
template:
metadata:
labels:
app: shopyseed-api
spec:
containers:
- name: api
image: your-registry/shopyseed-api:latest
ports:
- containerPort: 3011
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: shopyseed-secrets
key: database-url
- name: REDIS_URL
valueFrom:
secretKeyRef:
name: shopyseed-secrets
key: redis-url
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3011
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 3011
initialDelaySeconds: 5
periodSeconds: 5Database Setup
PostgreSQL Production Configuration
Recommended Settings
# postgresql.conf optimizations
shared_buffers = 256MB # 25% of RAM
effective_cache_size = 1GB # 75% of RAM
work_mem = 4MB # Per operation
maintenance_work_mem = 64MB # Maintenance operations
max_connections = 100 # Adjust based on loadDatabase Security
-- Create application user with limited permissions
CREATE USER shopyseed_app WITH PASSWORD 'strong_password';
-- Grant necessary permissions only
GRANT CONNECT ON DATABASE shopyseed_prod TO shopyseed_app;
GRANT USAGE ON SCHEMA public TO shopyseed_app;
GRANT CREATE ON SCHEMA public TO shopyseed_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO shopyseed_app;Backup Strategy
#!/bin/bash
# backup.sh - Daily database backup script
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"
DB_NAME="shopyseed_prod"
# Create backup
pg_dump -h localhost -U postgres -d $DB_NAME -f "$BACKUP_DIR/shopyseed_${DATE}.sql"
# Compress backup
gzip "$BACKUP_DIR/shopyseed_${DATE}.sql"
# Keep only last 7 days
find $BACKUP_DIR -name "shopyseed_*.sql.gz" -mtime +7 -delete
# Upload to S3 (optional)
aws s3 cp "$BACKUP_DIR/shopyseed_${DATE}.sql.gz" s3://your-backup-bucket/database/Stripe Configuration
Production Stripe Setup
1. Activate Live Mode
- Complete Stripe account verification
- Switch to Live mode in Stripe Dashboard
- Get live API keys
2. Configure Webhooks
# Webhook endpoint URL
https://api.yourdomain.com/billing/webhooks
# Events to listen for:
- customer.subscription.created
- customer.subscription.updated
- customer.subscription.deleted
- invoice.payment_succeeded
- invoice.payment_failed3. Payment Methods Configuration
// Enable payment methods in Stripe Dashboard
const paymentMethods = [
'card', // Credit/debit cards
'sepa_debit', // European bank transfers
'ideal', // Netherlands
'giropay', // Germany
'p24', // Poland
'bancontact', // Belgium
];4. Tax Configuration
// Configure tax rates in Stripe
const taxRates = {
'US': 0.0875, // 8.75% sales tax
'EU': 0.20, // 20% VAT
'CA': 0.13, // 13% HST
};Email Configuration
Recommended Email Providers
| Provider | Cost | Features | Setup Difficulty |
|---|---|---|---|
| Resend | Free tier available | Developer-friendly, great deliverability | Easy |
| SendGrid | Free tier available | Robust feature set, analytics | Medium |
| Amazon SES | Very low cost | High volume, requires setup | Hard |
| Mailgun | Free tier available | Good for transactional emails | Easy |
Resend Configuration (Recommended)
# Environment variables
EMAIL_HOST=smtp.resend.com
EMAIL_PORT=587
EMAIL_USER=resend
EMAIL_PASSWORD=your-resend-api-key
EMAIL_FROM=noreply@yourdomain.comEmail Templates
Configure email templates for:
- Welcome email after registration
- Email verification
- Password reset
- Organization invitations
- Billing notifications
// Email template configuration
const emailTemplates = {
welcome: {
subject: 'Welcome to ShopySeed!',
template: 'welcome.html'
},
verification: {
subject: 'Verify your email address',
template: 'verification.html'
},
invitation: {
subject: 'You\'ve been invited to join {{organizationName}}',
template: 'invitation.html'
}
};Security & SSL
SSL Certificate Setup
Let's Encrypt with Certbot
# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Get certificates
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com -d api.yourdomain.com
# Auto-renewal
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timerManual Certificate Installation
# nginx SSL configuration
ssl_certificate /path/to/certificate.pem;
ssl_certificate_key /path/to/private.key;
# SSL security settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;Security Headers
# Security headers in Nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.stripe.com;" always;Firewall Configuration
# UFW firewall setup
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Database access (only from application server)
sudo ufw allow from 10.0.0.0/24 to any port 5432Monitoring & Health Checks
Application Monitoring
Health Check Endpoints
ShopySeed provides built-in health check endpoints:
# Basic health check
curl https://api.yourdomain.com/health
# Readiness check (includes database)
curl https://api.yourdomain.com/health/readyResponse Examples
// Healthy response
{
"status": "ok",
"timestamp": "2024-01-15T10:30:00.000Z",
"uptime": 3600,
"version": "1.0.0",
"checks": {
"database": { "status": "ok", "responseTime": 12 },
"redis": { "status": "ok", "responseTime": 3 }
}
}
// Unhealthy response (503 status)
{
"status": "error",
"timestamp": "2024-01-15T10:30:00.000Z",
"checks": {
"database": { "status": "error", "error": "Connection timeout" },
"redis": { "status": "ok", "responseTime": 3 }
}
}External Monitoring
Uptime Monitoring
Configure external monitors to check:
- Main application URL
- API health endpoints
- Database connectivity
- Payment processing
Recommended Services:
- UptimeRobot (free tier available)
- Pingdom
- New Relic
- DataDog
Log Aggregation
# docker-compose.prod.yml - Add logging
services:
api:
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
labels: "service=api"Alerting
Set up alerts for:
- Application downtime
- Database connection failures
- High error rates (>5%)
- Payment processing failures
- Disk space usage (>80%)
- Memory usage (>90%)
Backup & Recovery
Database Backups
Automated Backup Script
#!/bin/bash
# /usr/local/bin/backup-shopyseed.sh
set -e
# Configuration
BACKUP_DIR="/backups/shopyseed"
DB_HOST="localhost"
DB_NAME="shopyseed_prod"
DB_USER="postgres"
S3_BUCKET="your-backup-bucket"
RETENTION_DAYS=30
# Create backup directory
mkdir -p $BACKUP_DIR
# Create backup
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/shopyseed_${DATE}.sql"
echo "Creating backup: $BACKUP_FILE"
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME > $BACKUP_FILE
# Compress
gzip $BACKUP_FILE
BACKUP_FILE_GZ="${BACKUP_FILE}.gz"
# Upload to S3
aws s3 cp $BACKUP_FILE_GZ s3://$S3_BUCKET/database/
# Clean old local backups
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
# Clean old S3 backups
aws s3api list-objects-v2 --bucket $S3_BUCKET --prefix database/ --query 'Contents[?LastModified<=`'$(date -d "$RETENTION_DAYS days ago" --iso-8601)'`].Key' --output text | xargs -I {} aws s3 rm s3://$S3_BUCKET/{}
echo "Backup completed successfully"Cron Job Setup
# Add to crontab: crontab -e
# Daily backup at 2 AM
0 2 * * * /usr/local/bin/backup-shopyseed.sh >> /var/log/shopyseed-backup.log 2>&1
# Weekly backup verification
0 3 * * 0 /usr/local/bin/verify-backup.sh >> /var/log/shopyseed-backup-verify.log 2>&1Disaster Recovery Plan
Recovery Time Objectives (RTO)
- Database Recovery: < 1 hour
- Application Recovery: < 30 minutes
- Complete System Recovery: < 4 hours
Recovery Procedures
# 1. Restore database from backup
pg_restore -h localhost -U postgres -d shopyseed_prod_restored backup_file.sql.gz
# 2. Update application configuration
# Point DATABASE_URL to restored database
# 3. Restart application services
docker compose -f docker-compose.prod.yml restart
# 4. Verify application functionality
curl https://api.yourdomain.com/health/readyPerformance Optimization
Database Performance
Index Optimization
-- Create indexes for common queries
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
CREATE INDEX CONCURRENTLY idx_organization_members_org_id ON organization_members(organization_id);
CREATE INDEX CONCURRENTLY idx_subscriptions_org_id ON subscriptions(organization_id);
-- Multi-tenant queries
CREATE INDEX CONCURRENTLY idx_tenant_data_org_id ON tenant_data(organization_id, created_at);Query Optimization
// Use Prisma query optimization
const organizations = await prisma.organization.findMany({
where: { id: { in: userOrganizationIds } },
include: {
members: {
select: { id: true, role: true, user: { select: { id: true, email: true } } }
},
subscription: { select: { plan: true, status: true } }
}
});Application Performance
Caching Strategy
// Redis caching implementation
@Injectable()
export class CacheService {
constructor(private redis: Redis) {}
async getOrSet<T>(key: string, fetcher: () => Promise<T>, ttl = 3600): Promise<T> {
const cached = await this.redis.get(key);
if (cached) {
return JSON.parse(cached);
}
const data = await fetcher();
await this.redis.setex(key, ttl, JSON.stringify(data));
return data;
}
}Connection Pooling
// Prisma connection pooling
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL
}
},
// Connection pooling
log: ['warn', 'error'],
});Frontend Performance
Next.js Optimization
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// Enable compression
compress: true,
// Image optimization
images: {
domains: ['yourdomain.com'],
formats: ['image/webp', 'image/avif'],
},
// Bundle analyzer
webpack: (config, { dev, isServer }) => {
if (!dev && !isServer) {
config.optimization.splitChunks.cacheGroups = {
...config.optimization.splitChunks.cacheGroups,
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2
}
};
}
return config;
}
};
module.exports = nextConfig;Scaling Considerations
Horizontal Scaling
Load Balancing
# nginx load balancer configuration
upstream api_backend {
least_conn;
server api-1:3011;
server api-2:3011;
server api-3:3011;
# Health checks
health_check interval=30s fails=3 passes=2;
}Database Scaling
// Read replica configuration
const prismaRead = new PrismaClient({
datasources: {
db: { url: process.env.DATABASE_READ_URL }
}
});
const prismaWrite = new PrismaClient({
datasources: {
db: { url: process.env.DATABASE_WRITE_URL }
}
});
// Use read replica for queries
const organizations = await prismaRead.organization.findMany();
// Use primary for writes
await prismaWrite.organization.create(data);Auto-Scaling
Kubernetes HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: shopyseed-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: shopyseed-api
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80Troubleshooting
Common Issues
1. Database Connection Failures
# Check database connectivity
docker compose -f docker-compose.prod.yml exec postgres psql -U postgres -d shopyseed_prod -c "SELECT version();"
# Check connection pool exhaustion
docker compose -f docker-compose.prod.yml logs api | grep "connection"2. Memory Issues
# Check memory usage
docker stats
# Check Node.js memory usage
docker compose -f docker-compose.prod.yml exec api node -e "console.log(process.memoryUsage())"3. SSL Certificate Issues
# Check certificate expiration
openssl x509 -in /etc/letsencrypt/live/yourdomain.com/cert.pem -text -noout | grep "Not After"
# Test SSL configuration
curl -I https://yourdomain.comDebugging Steps
-
Check Service Status
docker compose -f docker-compose.prod.yml ps -
Review Logs
docker compose -f docker-compose.prod.yml logs --tail=100 api -
Test Connectivity
curl -v https://api.yourdomain.com/health -
Database Health
docker compose -f docker-compose.prod.yml exec postgres pg_isready -
Resource Usage
docker system df docker system events
Production Checklist
Before going live, ensure you have completed:
Security
- SSL certificates installed and configured
- All default passwords changed
- Firewall properly configured
- Security headers implemented
- Rate limiting enabled
- CORS configured for production domains only
Performance
- Database optimized and indexed
- Caching implemented
- CDN configured for static assets
- Images optimized
- Bundle sizes minimized
Monitoring
- Health checks implemented
- Uptime monitoring configured
- Log aggregation set up
- Error tracking implemented
- Performance monitoring active
Backup & Recovery
- Automated database backups
- Backup restoration tested
- Disaster recovery plan documented
- Recovery procedures tested
Documentation
- API documentation updated
- Deployment procedures documented
- Troubleshooting guides created
- Contact information for emergencies
Your ShopySeed application is now ready for production! 🚀