Deployment Guide for Coherent.js Applications

This comprehensive guide covers deploying Coherent.js applications to various platforms, from traditional servers to modern cloud platforms and edge computing environments.

🚀 Quick Deployment Checklist

Before deploying your Coherent.js application:

  • Environment Configuration: Set up proper environment variables
  • Security Hardening: Enable HTTPS, set security headers
  • Performance Optimization: Enable caching and compression
  • Monitoring Setup: Configure logging and error tracking
  • Health Checks: Implement health check endpoints
  • Backup Strategy: Set up database and file backups
  • CI/CD Pipeline: Automate testing and deployment

🏗️ Platform-Specific Deployments

Docker Deployment

Production Dockerfile

# Multi-stage build for optimal size and security
FROM node:18-alpine AS base
WORKDIR /app
RUN apk add --no-cache dumb-init

FROM base AS deps
COPY package*.json ./
RUN npm ci --production --silent && npm cache clean --force

FROM base AS build
COPY package*.json ./
RUN npm ci --silent
COPY . .
RUN npm run build
RUN npm prune --production

FROM base AS runtime
# Create non-root user for security
RUN addgroup -g 1001 -S nodejs && \
    adduser -S coherent -u 1001

# Copy production dependencies and built application
COPY --from=deps --chown=coherent:nodejs /app/node_modules ./node_modules
COPY --from=build --chown=coherent:nodejs /app/dist ./dist
COPY --from=build --chown=coherent:nodejs /app/public ./public
COPY --from=build --chown=coherent:nodejs /app/package.json ./package.json
COPY --from=build --chown=coherent:nodejs /app/server.js ./server.js

# Optimize Node.js for production
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-old-space-size=2048 --optimize-for-size"
ENV UV_THREADPOOL_SIZE=16

# Health check configuration
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js || exit 1

# Switch to non-root user
USER coherent

# Expose port
EXPOSE 3000

# Use dumb-init to handle signals properly
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "server.js"]

Docker Compose for Development

# docker-compose.dev.yml
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://coherent:password@db:5432/coherent_dev
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: coherent_dev
      POSTGRES_USER: coherent
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    ports:
      - "5432:5432"
  
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

volumes:
  postgres_data:
  redis_data:

Production Docker Compose

# docker-compose.prod.yml
version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
      - REDIS_URL=${REDIS_URL}
      - SECRET_KEY=${SECRET_KEY}
    depends_on:
      - db
      - redis
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.coherent.rule=Host(\`example.com\`)"
      - "traefik.http.routers.coherent.tls.certresolver=le"

  nginx:
    image: nginx:alpine
    restart: unless-stopped
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./static:/var/www/static:ro
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - app

  db:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./backups:/backups
    
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes

  backup:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      PGPASSWORD: ${DB_PASSWORD}
    volumes:
      - ./backups:/backups
    command: |
      sh -c "
        while true; do
          pg_dump -h db -U ${DB_USER} ${DB_NAME} > /backups/backup_$(date +%Y%m%d_%H%M%S).sql
          find /backups -name '*.sql' -mtime +7 -delete
          sleep 86400
        done
      "

volumes:
  postgres_data:
  redis_data:

Kubernetes Deployment

Deployment Configuration

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coherent-app
  labels:
    app: coherent-app
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: coherent-app
  template:
    metadata:
      labels:
        app: coherent-app
    spec:
      containers:
      - name: coherent-app
        image: coherent-app:latest
        ports:
        - containerPort: 3000
        env:
        - name: NODE_ENV
          value: "production"
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: coherent-secrets
              key: database-url
        - name: REDIS_URL
          valueFrom:
            secretKeyRef:
              name: coherent-secrets
              key: redis-url
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        readinessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 10
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /health
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 10
        volumeMounts:
        - name: config
          mountPath: /app/config
          readOnly: true
      volumes:
      - name: config
        configMap:
          name: coherent-config
      imagePullSecrets:
      - name: registry-secret
---
apiVersion: v1
kind: Service
metadata:
  name: coherent-service
spec:
  selector:
    app: coherent-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 3000
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: coherent-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
  tls:
  - hosts:
    - example.com
    secretName: coherent-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: coherent-service
            port:
              number: 80

ConfigMap and Secrets

# k8s/config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: coherent-config
data:
  cache-size: "10000"
  log-level: "info"
  metrics-enabled: "true"
---
apiVersion: v1
kind: Secret
metadata:
  name: coherent-secrets
type: Opaque
data:
  database-url: <base64-encoded-database-url>
  redis-url: <base64-encoded-redis-url>
  secret-key: <base64-encoded-secret-key>

AWS Deployment

Elastic Beanstalk

// .ebextensions/nodecommand.config
{
  "option_settings": [
    {
      "namespace": "aws:elasticbeanstalk:container:nodejs",
      "option_name": "NodeCommand",
      "value": "npm start"
    },
    {
      "namespace": "aws:elasticbeanstalk:container:nodejs",
      "option_name": "NodeVersion",
      "value": "18.x"
    },
    {
      "namespace": "aws:elasticbeanstalk:application:environment",
      "option_name": "NODE_ENV",
      "value": "production"
    },
    {
      "namespace": "aws:elasticbeanstalk:application:environment",
      "option_name": "PORT",
      "value": "8080"
    }
  ]
}
# .ebextensions/https-redirect.config
Resources:
  AWSEBV2LoadBalancerListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: redirect
          RedirectConfig:
            Protocol: HTTPS
            Port: 443
            StatusCode: HTTP_301
      LoadBalancerArn:
        Ref: AWSEBV2LoadBalancer
      Port: 80
      Protocol: HTTP

ECS with Fargate

// ecs-task-definition.json
{
  "family": "coherent-app",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::account:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::account:role/ecsTaskRole",
  "containerDefinitions": [
    {
      "name": "coherent-app",
      "image": "your-account.dkr.ecr.region.amazonaws.com/coherent-app:latest",
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "NODE_ENV",
          "value": "production"
        }
      ],
      "secrets": [
        {
          "name": "DATABASE_URL",
          "valueFrom": "arn:aws:secretsmanager:region:account:secret:coherent/database-url"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/coherent-app",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "healthCheck": {
        "command": ["CMD-SHELL", "curl -f http://localhost:3000/health || exit 1"],
        "interval": 30,
        "timeout": 5,
        "retries": 3
      }
    }
  ]
}

Serverless Deployment

Vercel

// vercel.json
{
  "version": 2,
  "builds": [
    {
      "src": "api/**/*.js",
      "use": "@vercel/node"
    },
    {
      "src": "public/**",
      "use": "@vercel/static"
    }
  ],
  "routes": [
    {
      "src": "/api/(.*)",
      "dest": "/api/$1"
    },
    {
      "src": "/(.*)",
      "dest": "/api/app.js"
    }
  ],
  "env": {
    "NODE_ENV": "production"
  },
  "functions": {
    "api/app.js": {
      "maxDuration": 30
    }
  }
}
// api/app.js - Serverless entry point
import { createCoherent, renderToString } from 'coherent-js';
import { HomePage } from '../components/HomePage.js';

const coherent = createCoherent({
  enableCache: true,
  cacheSize: 1000
});

export default async function handler(req, res) {
  try {
    const props = {
      path: req.url,
      query: req.query,
      headers: req.headers
    };
    
    const html = coherent.render(HomePage(props));
    
    res.setHeader('Content-Type', 'text/html');
    res.setHeader('Cache-Control', 's-maxage=300, stale-while-revalidate');
    res.status(200).send(html);
  } catch (error) {
    console.error('Render error:', error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
}

Netlify Functions

// netlify/functions/ssr.js
import { createCoherent } from 'coherent-js';
import { App } from '../../src/App.js';

const coherent = createCoherent({
  enableCache: true,
  cacheSize: 500
});

export const handler = async (event, context) => {
  try {
    const props = {
      path: event.path,
      queryStringParameters: event.queryStringParameters,
      headers: event.headers
    };
    
    const html = coherent.render(App(props));
    
    return {
      statusCode: 200,
      headers: {
        'Content-Type': 'text/html',
        'Cache-Control': 'public, max-age=300'
      },
      body: html
    };
  } catch (error) {
    console.error('Function error:', error);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Internal Server Error' })
    };
  }
};

🔧 Production Configuration

Environment Variables

# .env.production
NODE_ENV=production
PORT=3000

# Database
DATABASE_URL=postgresql://user:password@host:5432/database
DATABASE_POOL_SIZE=20
DATABASE_SSL=true

# Cache
REDIS_URL=redis://user:password@host:6379
CACHE_TTL=300
CACHE_SIZE=10000

# Security
SECRET_KEY=your-super-secret-key
JWT_SECRET=your-jwt-secret
COOKIE_SECRET=your-cookie-secret
ALLOWED_ORIGINS=https://example.com,https://www.example.com

# Monitoring
SENTRY_DSN=https://your-sentry-dsn
LOG_LEVEL=info
METRICS_ENABLED=true

# Performance
UV_THREADPOOL_SIZE=16
NODE_OPTIONS=--max-old-space-size=2048 --optimize-for-size

Production Server Configuration

// server.js - Production-ready server
import express from 'express';
import compression from 'compression';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { createCoherent } from 'coherent-js';
import { setupMonitoring } from './monitoring.js';
import { setupHealthChecks } from './health.js';

const app = express();
const PORT = process.env.PORT || 3000;

// Security middleware
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      scriptSrc: ["'self'"],
      imgSrc: ["'self'", "data:", "https:"],
    },
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  }
}));

// Compression middleware
app.use(compression({
  filter: (req, res) => {
    if (req.headers['x-no-compression']) return false;
    return compression.filter(req, res);
  },
  level: 6,
  threshold: 1024
}));

// Rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // Limit each IP to 100 requests per windowMs
  standardHeaders: true,
  legacyHeaders: false,
  message: {
    error: 'Too many requests, please try again later.'
  }
});

app.use(limiter);

// Static files with long-term caching
app.use('/static', express.static('public', {
  maxAge: '1y',
  immutable: true,
  etag: false
}));

// Initialize Coherent.js
const coherent = createCoherent({
  enableCache: true,
  cacheSize: parseInt(process.env.CACHE_SIZE) || 10000,
  enableMonitoring: true
});

// Setup monitoring and health checks
setupMonitoring(app);
setupHealthChecks(app);

// Main application routes
app.get('*', async (req, res) => {
  try {
    const props = {
      path: req.path,
      query: req.query,
      user: req.user,
      headers: req.headers
    };
    
    const html = coherent.render(App(props));
    
    // Cache headers
    res.set({
      'Cache-Control': 'public, max-age=300, s-maxage=3600',
      'Vary': 'Accept-Encoding'
    });
    
    res.send(html);
  } catch (error) {
    console.error('Render error:', error);
    res.status(500).send('Internal Server Error');
  }
});

// Error handler
app.use((err, req, res, next) => {
  console.error('Application error:', err);
  
  if (process.env.NODE_ENV === 'production') {
    res.status(500).json({ error: 'Internal Server Error' });
  } else {
    res.status(500).json({ error: err.message, stack: err.stack });
  }
});

// Graceful shutdown
const server = app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');
  server.close(() => {
    console.log('Process terminated');
    process.exit(0);
  });
});

process.on('SIGINT', () => {
  console.log('SIGINT received, shutting down gracefully');
  server.close(() => {
    console.log('Process terminated');
    process.exit(0);
  });
});

Health Check Implementation

// health.js
import { performanceMonitor } from 'coherent-js';
import { checkDatabase, checkRedis } from './services.js';

export const setupHealthChecks = (app) => {
  // Basic health check
  app.get('/health', (req, res) => {
    res.status(200).json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      pid: process.pid
    });
  });

  // Detailed health check
  app.get('/health/detailed', async (req, res) => {
    const checks = {
      server: true,
      database: false,
      redis: false,
      coherent: false
    };

    const results = {
      status: 'healthy',
      timestamp: new Date().toISOString(),
      checks,
      details: {}
    };

    try {
      // Check database
      await checkDatabase();
      checks.database = true;
      results.details.database = 'Connected';
    } catch (error) {
      checks.database = false;
      results.details.database = error.message;
      results.status = 'unhealthy';
    }

    try {
      // Check Redis
      await checkRedis();
      checks.redis = true;
      results.details.redis = 'Connected';
    } catch (error) {
      checks.redis = false;
      results.details.redis = error.message;
      results.status = 'degraded';
    }

    // Check Coherent.js performance
    const stats = performanceMonitor.getStats();
    if (stats.averageRenderTime < 100) {
      checks.coherent = true;
      results.details.coherent = `Avg render: ${stats.averageRenderTime}ms`;
    } else {
      checks.coherent = false;
      results.details.coherent = 'Performance degraded';
      results.status = 'degraded';
    }

    const statusCode = results.status === 'healthy' ? 200 : 
                      results.status === 'degraded' ? 200 : 500;

    res.status(statusCode).json(results);
  });

  // Readiness probe
  app.get('/ready', async (req, res) => {
    try {
      await checkDatabase();
      res.status(200).json({ status: 'ready' });
    } catch (error) {
      res.status(503).json({ status: 'not ready', error: error.message });
    }
  });
};

🚨 Monitoring and Logging

Application Monitoring

// monitoring.js
import prometheus from 'prom-client';
import { performanceMonitor } from 'coherent-js';

const register = prometheus.register;

// Default metrics
prometheus.collectDefaultMetrics();

// Custom metrics
const httpRequestDuration = new prometheus.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds',
  labelNames: ['method', 'route', 'status']
});

const coherentRenderDuration = new prometheus.Histogram({
  name: 'coherent_render_duration_seconds',
  help: 'Duration of Coherent.js renders in seconds',
  labelNames: ['component']
});

const cacheHitRate = new prometheus.Gauge({
  name: 'coherent_cache_hit_rate',
  help: 'Cache hit rate percentage'
});

export const setupMonitoring = (app) => {
  // Middleware to track request metrics
  app.use((req, res, next) => {
    const start = Date.now();
    
    res.on('finish', () => {
      const duration = (Date.now() - start) / 1000;
      httpRequestDuration
        .labels(req.method, req.route?.path || req.path, res.statusCode)
        .observe(duration);
    });
    
    next();
  });

  // Coherent.js metrics integration
  performanceMonitor.on('render', (data) => {
    coherentRenderDuration
      .labels(data.component)
      .observe(data.duration / 1000);
  });

  // Update cache metrics periodically
  setInterval(() => {
    const stats = performanceMonitor.getStats();
    cacheHitRate.set(stats.cacheHitRate);
  }, 30000);

  // Metrics endpoint
  app.get('/metrics', async (req, res) => {
    res.set('Content-Type', register.contentType);
    const metrics = await register.metrics();
    res.send(metrics);
  });

  // Performance dashboard
  app.get('/admin/performance', (req, res) => {
    const stats = performanceMonitor.getStats();
    
    const dashboard = {
      div: {
        children: [
          { h1: { text: 'Performance Dashboard' } },
          {
            div: {
              className: 'metrics-grid',
              children: [
                {
                  div: {
                    className: 'metric-card',
                    children: [
                      { h3: { text: 'Render Performance' } },
                      { p: { text: `Average: ${stats.averageRenderTime}ms` } },
                      { p: { text: `95th percentile: ${stats.p95RenderTime}ms` } }
                    ]
                  }
                },
                {
                  div: {
                    className: 'metric-card',
                    children: [
                      { h3: { text: 'Cache Performance' } },
                      { p: { text: `Hit rate: ${stats.cacheHitRate}%` } },
                      { p: { text: `Total hits: ${stats.totalCacheHits}` } }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    };
    
    res.send(renderToString(dashboard));
  });
};

Structured Logging

// logger.js
import winston from 'winston';
import { performanceMonitor } from 'coherent-js';

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: {
    service: 'coherent-app',
    environment: process.env.NODE_ENV
  },
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({
      filename: 'logs/error.log',
      level: 'error'
    }),
    new winston.transports.File({
      filename: 'logs/combined.log'
    })
  ]
});

// Log Coherent.js performance events
performanceMonitor.on('slowRender', (data) => {
  logger.warn('Slow render detected', {
    component: data.component,
    duration: data.duration,
    threshold: data.threshold
  });
});

performanceMonitor.on('cacheHit', (data) => {
  logger.debug('Cache hit', {
    key: data.key,
    level: data.level
  });
});

export default logger;

🔄 CI/CD Pipeline

GitHub Actions

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '18'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: coherent_test
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
          - 5432:5432

    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Run linting
        run: npm run lint
      
      - name: Run type checking
        run: npm run type-check
      
      - name: Run tests
        run: npm test
        env:
          DATABASE_URL: postgresql://postgres:postgres@localhost:5432/coherent_test
      
      - name: Run E2E tests
        run: npm run test:e2e
      
      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Docker Buildx
        uses: docker/setup-buildx-action@v2
      
      - name: Login to Container Registry
        uses: docker/login-action@v2
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=sha
            type=raw,value=latest,enable={{is_default_branch}}
      
      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    environment: production
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Kubernetes
        uses: azure/k8s-deploy@v1
        with:
          method: kubectl
          kubeconfig: ${{ secrets.KUBE_CONFIG }}
          manifests: |
            k8s/deployment.yaml
            k8s/service.yaml
            k8s/ingress.yaml
          images: |
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
      
      - name: Verify deployment
        run: |
          kubectl rollout status deployment/coherent-app -w
          kubectl get services -o wide

GitLab CI

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

test:
  stage: test
  image: node:18-alpine
  services:
    - postgres:15-alpine
  variables:
    POSTGRES_DB: coherent_test
    POSTGRES_USER: postgres
    POSTGRES_PASSWORD: postgres
    DATABASE_URL: postgresql://postgres:postgres@postgres:5432/coherent_test
  script:
    - npm ci
    - npm run lint
    - npm run type-check
    - npm test
    - npm run test:e2e
  coverage: '/Statements\s*:\s*([^%]+)/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main

deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $KUBE_CONTEXT
    - kubectl set image deployment/coherent-app coherent-app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - kubectl rollout status deployment/coherent-app
  environment:
    name: production
    url: https://example.com
  only:
    - main
  when: manual

🔧 Maintenance and Scaling

Database Migrations

// migrations/001_initial_schema.js
export const up = async (db) => {
  await db.schema.createTable('users', table => {
    table.increments('id').primary();
    table.string('email').unique().notNullable();
    table.string('name').notNullable();
    table.timestamps(true, true);
  });
  
  await db.schema.createTable('posts', table => {
    table.increments('id').primary();
    table.integer('user_id').references('users.id').onDelete('CASCADE');
    table.string('title').notNullable();
    table.text('content');
    table.timestamps(true, true);
  });
};

export const down = async (db) => {
  await db.schema.dropTable('posts');
  await db.schema.dropTable('users');
};

Backup Strategy

#!/bin/bash
# backup.sh - Database backup script

set -euo pipefail

BACKUP_DIR="/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DB_NAME=${DB_NAME:-coherent}
RETENTION_DAYS=${RETENTION_DAYS:-7}

# Create backup directory
mkdir -p $BACKUP_DIR

# Database backup
echo "Starting database backup..."
pg_dump $DATABASE_URL > $BACKUP_DIR/db_backup_$TIMESTAMP.sql

# Compress backup
gzip $BACKUP_DIR/db_backup_$TIMESTAMP.sql

# Upload to S3 (optional)
if [ -n "${AWS_S3_BUCKET:-}" ]; then
  aws s3 cp $BACKUP_DIR/db_backup_$TIMESTAMP.sql.gz s3://$AWS_S3_BUCKET/backups/
fi

# Clean up old backups
find $BACKUP_DIR -name "db_backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup completed: db_backup_$TIMESTAMP.sql.gz"

Scaling Configuration

# k8s/hpa.yaml - Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: coherent-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: coherent-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60

This comprehensive deployment guide covers all aspects of deploying Coherent.js applications from development to production, ensuring reliability, security, and scalability.