Deployment Production Implementation

1. Vercel Netlify Jamstack Hosting

Deploy frontend applications to modern hosting platforms with automatic builds, CDN distribution, and serverless functions.

Platform Best For Key Features Pricing
Vercel Next.js, React apps Edge network, ISR, serverless Free hobby, $20+/mo pro
Netlify Static sites, Jamstack Form handling, split testing Free starter, $19+/mo pro
Cloudflare Pages Static sites, workers Unlimited bandwidth, fast CDN Free unlimited
AWS Amplify Full-stack apps Backend integration, auth Pay per build
GitHub Pages Static sites, docs Free hosting, Jekyll support Free

Example: Vercel deployment configuration

// vercel.json
{
  "version": 2,
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/next"
    }
  ],
  "routes": [
    {
      "src": "/api/(.*)",
      "dest": "/api/$1"
    },
    {
      "src": "/(.*)",
      "dest": "/$1"
    }
  ],
  "env": {
    "NEXT_PUBLIC_API_URL": "https://api.example.com",
    "DATABASE_URL": "@database_url"
  },
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-XSS-Protection",
          "value": "1; mode=block"
        }
      ]
    },
    {
      "source": "/static/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ],
  "redirects": [
    {
      "source": "/old-page",
      "destination": "/new-page",
      "permanent": true
    }
  ],
  "rewrites": [
    {
      "source": "/blog/:path*",
      "destination": "https://blog.example.com/:path*"
    }
  ]
}

// Deploy via CLI
npm install -g vercel
vercel login
vercel --prod

// Deploy via Git integration (automatic)
// Push to main branch → auto-deploy to production
// Push to other branches → preview deployments

// Environment variables (via Vercel Dashboard or CLI)
vercel env add NEXT_PUBLIC_API_URL production
vercel env add DATABASE_URL production

// Preview URLs for each PR
// https://my-app-git-feature-branch-username.vercel.app

Example: Netlify deployment configuration

// netlify.toml
[build]
  base = "/"
  publish = "dist"
  command = "npm run build"

[build.environment]
  NODE_VERSION = "18"
  NPM_FLAGS = "--legacy-peer-deps"

# Redirect rules
[[redirects]]
  from = "/old-url"
  to = "/new-url"
  status = 301

[[redirects]]
  from = "/api/*"
  to = "https://api.example.com/:splat"
  status = 200

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200  # SPA fallback

# Headers
[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    X-Content-Type-Options = "nosniff"
    Referrer-Policy = "strict-origin-when-cross-origin"

[[headers]]
  for = "/static/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

# Functions (serverless)
[functions]
  directory = "netlify/functions"
  node_bundler = "esbuild"

# Dev server
[dev]
  command = "npm run dev"
  port = 3000
  publish = "dist"

# Deploy contexts
[context.production]
  environment = { NODE_ENV = "production" }

[context.deploy-preview]
  environment = { NODE_ENV = "staging" }

[context.branch-deploy]
  environment = { NODE_ENV = "development" }

# Form handling (Netlify feature)
# In HTML:
<form name="contact" method="POST" data-netlify="true">
  <input type="text" name="name" />
  <input type="email" name="email" />
  <button type="submit">Submit</button>
</form>

# Deploy via CLI
npm install -g netlify-cli
netlify login
netlify init
netlify deploy --prod

Example: Cloudflare Pages deployment

// wrangler.toml (for Pages with Functions)
name = "my-app"
compatibility_date = "2024-01-01"

[build]
  command = "npm run build"
  cwd = "."
  watch_dir = "src"

[[build.upload]]
  format = "service-worker"
  main = "./functions/[[path]].js"

[env.production]
  [env.production.vars]
    API_URL = "https://api.example.com"

# _redirects file (in public folder)
/old-url  /new-url  301
/api/*    https://api.example.com/:splat  200
/*        /index.html  200

# _headers file
/*
  X-Frame-Options: DENY
  X-XSS-Protection: 1; mode=block
  X-Content-Type-Options: nosniff

/static/*
  Cache-Control: public, max-age=31536000, immutable

# Cloudflare Pages Function
// functions/api/hello.ts
export async function onRequest(context) {
  const { request, env, params } = context;
  
  return new Response(JSON.stringify({
    message: 'Hello from Cloudflare Pages',
    time: new Date().toISOString()
  }), {
    headers: { 'Content-Type': 'application/json' }
  });
}

# Deploy via CLI
npm install -g wrangler
wrangler login
wrangler pages publish dist --project-name=my-app

# Or use Git integration (automatic)
# Connect GitHub repo → automatic deployments
Platform Selection: Vercel for Next.js apps with edge functions. Netlify for static sites with forms and split testing. Cloudflare Pages for unlimited bandwidth. All provide automatic HTTPS, CDN, preview deployments, and Git integration.

2. Docker Container Frontend Apps

Containerize frontend applications with Docker for consistent deployments across environments and orchestration with Kubernetes.

Strategy Use Case Benefits Complexity
Multi-stage Build Production optimization Smaller images, faster builds Medium
Nginx Serving Static files, reverse proxy Fast, efficient, caching Low
Node.js SSR Next.js, server rendering Dynamic content, APIs Medium
Docker Compose Multi-container setup Local dev, testing Medium

Example: Multi-stage Dockerfile for React app

# Dockerfile - Multi-stage build for production

# Stage 1: Build
FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production && \
    npm cache clean --force

# Copy source code
COPY . .

# Build app
RUN npm run build

# Stage 2: Production
FROM nginx:alpine AS production

# Copy custom nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Copy built assets from builder
COPY --from=builder /app/dist /usr/share/nginx/html

# Add healthcheck
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost:80/health || exit 1

# Expose port
EXPOSE 80

# Start nginx
CMD ["nginx", "-g", "daemon off;"]

# Build and run
# docker build -t my-app:latest .
# docker run -p 8080:80 my-app:latest

Example: Nginx configuration for SPA

# nginx.conf
server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript 
               application/x-javascript application/xml+rss 
               application/javascript application/json;

    # Security headers
    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;

    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # API proxy (optional)
    location /api {
        proxy_pass http://backend-service:3000;
        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;
    }

    # SPA fallback - serve index.html for all routes
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }

    # Deny access to hidden files
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

Example: Next.js SSR Dockerfile

# Dockerfile for Next.js
FROM node:18-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Build Next.js app
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Copy necessary files
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static

# Set correct permissions
USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["node", "server.js"]

# next.config.js - Enable standalone output
module.exports = {
  output: 'standalone'
}

Example: Docker Compose for full-stack development

# docker-compose.yml
version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:80"
    environment:
      - REACT_APP_API_URL=http://localhost:4000
    depends_on:
      - backend
    networks:
      - app-network
    volumes:
      - ./frontend/src:/app/src  # Hot reload in dev

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "4000:4000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
      - NODE_ENV=development
    depends_on:
      - db
    networks:
      - app-network

  db:
    image: postgres:15-alpine
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mydb
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - app-network

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - frontend
      - backend
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

volumes:
  postgres-data:

# Commands
# docker-compose up -d
# docker-compose down
# docker-compose logs -f frontend
# docker-compose exec frontend sh
Security Best Practices: Use multi-stage builds to reduce image size. Run as non-root user. Scan images for vulnerabilities with docker scan. Use .dockerignore to exclude unnecessary files. Pin base image versions.

3. CDN CloudFront Asset Optimization

Distribute static assets globally with CDN for faster load times, reduced latency, and improved user experience worldwide.

CDN Provider Key Features Best For Pricing Model
CloudFront (AWS) Global edge, Lambda@Edge AWS ecosystem integration Pay per request
Cloudflare DDoS protection, workers Security, free tier Free + paid plans
Fastly Instant purge, VCL Real-time apps Pay as you go
Akamai Largest network Enterprise scale Enterprise pricing

Example: CloudFront distribution setup with Terraform

# main.tf - CloudFront + S3 setup
resource "aws_s3_bucket" "frontend" {
  bucket = "my-app-frontend"
}

resource "aws_s3_bucket_public_access_block" "frontend" {
  bucket = aws_s3_bucket.frontend.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_cloudfront_origin_access_identity" "frontend" {
  comment = "OAI for frontend bucket"
}

resource "aws_s3_bucket_policy" "frontend" {
  bucket = aws_s3_bucket.frontend.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowCloudFrontAccess"
        Effect = "Allow"
        Principal = {
          AWS = aws_cloudfront_origin_access_identity.frontend.iam_arn
        }
        Action   = "s3:GetObject"
        Resource = "${aws_s3_bucket.frontend.arn}/*"
      }
    ]
  })
}

resource "aws_cloudfront_distribution" "frontend" {
  enabled             = true
  is_ipv6_enabled     = true
  comment             = "Frontend distribution"
  default_root_object = "index.html"
  price_class         = "PriceClass_100"
  aliases             = ["www.example.com", "example.com"]

  origin {
    domain_name = aws_s3_bucket.frontend.bucket_regional_domain_name
    origin_id   = "S3-Frontend"

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.frontend.cloudfront_access_identity_path
    }
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD", "OPTIONS"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "S3-Frontend"

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
    compress               = true
  }

  # Cache behavior for static assets
  ordered_cache_behavior {
    path_pattern     = "/static/*"
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "S3-Frontend"

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }

    min_ttl                = 31536000
    default_ttl            = 31536000
    max_ttl                = 31536000
    compress               = true
    viewer_protocol_policy = "redirect-to-https"
  }

  # SPA fallback
  custom_error_response {
    error_code         = 404
    response_code      = 200
    response_page_path = "/index.html"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    acm_certificate_arn      = aws_acm_certificate.cert.arn
    ssl_support_method       = "sni-only"
    minimum_protocol_version = "TLSv1.2_2021"
  }

  tags = {
    Environment = "production"
  }
}

Example: CDN cache control headers

// Cache control strategy for different asset types

// 1. HTML files - No cache (always fresh)
Cache-Control: no-cache, no-store, must-revalidate
// Or short cache with revalidation
Cache-Control: max-age=0, must-revalidate

// 2. JavaScript/CSS with hash in filename
// main.a1b2c3d4.js, styles.e5f6g7h8.css
Cache-Control: public, max-age=31536000, immutable

// 3. Images, fonts with hash
// logo.i9j0k1l2.png
Cache-Control: public, max-age=31536000, immutable

// 4. API responses
Cache-Control: max-age=60, s-maxage=300, stale-while-revalidate=86400

// 5. Dynamic content
Cache-Control: private, max-age=0, must-revalidate

// Next.js automatic cache headers
// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=0, must-revalidate'
          }
        ]
      },
      {
        source: '/_next/static/:path*',
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=31536000, immutable'
          }
        ]
      },
      {
        source: '/images/:path*',
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=86400, s-maxage=604800'
          }
        ]
      }
    ];
  }
};

// Webpack output with content hash
output: {
  filename: '[name].[contenthash].js',
  chunkFilename: '[name].[contenthash].chunk.js'
}

// CloudFront cache invalidation
aws cloudfront create-invalidation \
  --distribution-id E1234ABCD5678 \
  --paths "/*"

// Selective invalidation (cheaper)
aws cloudfront create-invalidation \
  --distribution-id E1234ABCD5678 \
  --paths "/index.html" "/manifest.json"

Example: Cloudflare Workers for edge optimization

// workers/optimize-images.js
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    
    // Check if WebP is supported
    const acceptHeader = request.headers.get('Accept') || '';
    const supportsWebP = acceptHeader.includes('image/webp');
    
    // Transform image format at edge
    if (url.pathname.match(/\.(jpg|png)$/)) {
      const imageRequest = new Request(request);
      
      if (supportsWebP) {
        // Serve WebP version
        const webpUrl = url.pathname.replace(/\.(jpg|png)$/, '.webp');
        return fetch(new Request(webpUrl, imageRequest));
      }
    }
    
    // Add custom headers
    const response = await fetch(request);
    const newResponse = new Response(response.body, response);
    
    // Cache static assets aggressively
    if (url.pathname.startsWith('/static/')) {
      newResponse.headers.set('Cache-Control', 'public, max-age=31536000, immutable');
    }
    
    // Security headers
    newResponse.headers.set('X-Content-Type-Options', 'nosniff');
    newResponse.headers.set('X-Frame-Options', 'DENY');
    
    return newResponse;
  }
};

// wrangler.toml
name = "image-optimizer"
main = "workers/optimize-images.js"
compatibility_date = "2024-01-01"

[env.production]
route = "example.com/*"
CDN Best Practices: Use content hashing for immutable assets. Set aggressive cache headers for static files. Invalidate cache selectively. Enable compression (Gzip/Brotli). Use HTTP/2 push for critical resources. Monitor CDN hit ratio.

4. Environment Variables Config

Manage environment-specific configuration securely across development, staging, and production environments.

Approach Use Case Security Complexity
.env Files Local development Low (gitignored) Low
Platform Secrets Vercel/Netlify secrets High (encrypted) Low
AWS Secrets Manager Production secrets High (encrypted, rotated) Medium
HashiCorp Vault Enterprise secrets Very High High

Example: Environment variables setup with validation

// .env.example (commit to git)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
DATABASE_URL=postgresql://localhost:5432/mydb
JWT_SECRET=your-secret-key-here
STRIPE_SECRET_KEY=sk_test_xxx

// .env.local (gitignored - actual values)
NEXT_PUBLIC_API_URL=http://localhost:4000
NEXT_PUBLIC_GA_ID=G-123456789
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb_dev
JWT_SECRET=super-secret-dev-key
STRIPE_SECRET_KEY=sk_test_actual_key

// .env.production (production values - use secrets manager)
NEXT_PUBLIC_API_URL=https://api.production.com
NEXT_PUBLIC_GA_ID=G-PROD123456
DATABASE_URL=@database-url-secret
JWT_SECRET=@jwt-secret
STRIPE_SECRET_KEY=@stripe-secret

// .gitignore
.env*.local
.env.production

// config/env.ts - Type-safe environment variables
import { z } from 'zod';

const envSchema = z.object({
  // Public variables (available in browser)
  NEXT_PUBLIC_API_URL: z.string().url(),
  NEXT_PUBLIC_GA_ID: z.string().optional(),
  
  // Server-only variables
  DATABASE_URL: z.string(),
  JWT_SECRET: z.string().min(32),
  STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
  
  // Environment
  NODE_ENV: z.enum(['development', 'staging', 'production']).default('development')
});

// Validate and export
const _env = envSchema.safeParse(process.env);

if (!_env.success) {
  console.error('❌ Invalid environment variables:', _env.error.format());
  throw new Error('Invalid environment variables');
}

export const env = _env.data;

// Usage
import { env } from '@/config/env';

console.log(env.NEXT_PUBLIC_API_URL); // Type-safe access
console.log(env.JWT_SECRET); // Only available server-side

Example: Multiple environment configurations

// config/environments.ts
interface AppConfig {
  apiUrl: string;
  environment: 'development' | 'staging' | 'production';
  features: {
    analytics: boolean;
    errorTracking: boolean;
    debugMode: boolean;
  };
  endpoints: {
    api: string;
    auth: string;
    cdn: string;
  };
}

const development: AppConfig = {
  apiUrl: 'http://localhost:4000',
  environment: 'development',
  features: {
    analytics: false,
    errorTracking: false,
    debugMode: true
  },
  endpoints: {
    api: 'http://localhost:4000/api',
    auth: 'http://localhost:4000/auth',
    cdn: 'http://localhost:3000'
  }
};

const staging: AppConfig = {
  apiUrl: 'https://api-staging.example.com',
  environment: 'staging',
  features: {
    analytics: true,
    errorTracking: true,
    debugMode: true
  },
  endpoints: {
    api: 'https://api-staging.example.com/api',
    auth: 'https://api-staging.example.com/auth',
    cdn: 'https://cdn-staging.example.com'
  }
};

const production: AppConfig = {
  apiUrl: 'https://api.example.com',
  environment: 'production',
  features: {
    analytics: true,
    errorTracking: true,
    debugMode: false
  },
  endpoints: {
    api: 'https://api.example.com/api',
    auth: 'https://api.example.com/auth',
    cdn: 'https://cdn.example.com'
  }
};

const configs = { development, staging, production };

export const config = configs[process.env.NODE_ENV || 'development'];

// Feature flags
export const isProduction = config.environment === 'production';
export const isDevelopment = config.environment === 'development';
export const isStaging = config.environment === 'staging';

// Usage
import { config, isProduction } from '@/config/environments';

if (isProduction) {
  initAnalytics(config.endpoints.api);
}

Example: AWS Secrets Manager integration

// Installation
npm install @aws-sdk/client-secrets-manager

// lib/secrets.ts
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';

const client = new SecretsManagerClient({
  region: process.env.AWS_REGION || 'us-east-1'
});

export async function getSecret(secretName: string): Promise<any> {
  try {
    const command = new GetSecretValueCommand({
      SecretId: secretName
    });
    
    const response = await client.send(command);
    
    if (response.SecretString) {
      return JSON.parse(response.SecretString);
    }
    
    // Binary secret
    const buff = Buffer.from(response.SecretBinary as Uint8Array);
    return buff.toString('ascii');
  } catch (error) {
    console.error('Error retrieving secret:', error);
    throw error;
  }
}

// Cache secrets in memory
const secretsCache = new Map<string, any>();

export async function getCachedSecret(secretName: string): Promise<any> {
  if (secretsCache.has(secretName)) {
    return secretsCache.get(secretName);
  }
  
  const secret = await getSecret(secretName);
  secretsCache.set(secretName, secret);
  
  // Refresh after 1 hour
  setTimeout(() => {
    secretsCache.delete(secretName);
  }, 60 * 60 * 1000);
  
  return secret;
}

// Usage in Next.js API route
export async function GET() {
  const secrets = await getCachedSecret('prod/api/keys');
  
  const response = await fetch(secrets.API_URL, {
    headers: {
      'Authorization': `Bearer ${secrets.API_KEY}`
    }
  });
  
  return Response.json(await response.json());
}

// Terraform to create secret
resource "aws_secretsmanager_secret" "api_keys" {
  name = "prod/api/keys"
  description = "API keys for production"
}

resource "aws_secretsmanager_secret_version" "api_keys" {
  secret_id = aws_secretsmanager_secret.api_keys.id
  secret_string = jsonencode({
    API_URL = "https://api.example.com"
    API_KEY = "secret-key-value"
    STRIPE_KEY = "sk_live_xxx"
  })
}
Security Best Practices: Never commit secrets to git. Use .env.example for documentation. Rotate secrets regularly. Use different secrets per environment. Prefix public variables with NEXT_PUBLIC_ or VITE_. Validate all env vars.

5. Blue-Green Canary Deployment

Implement zero-downtime deployment strategies with instant rollback capabilities and gradual traffic shifting.

Strategy Approach Risk Rollback Time
Blue-Green Switch all traffic instantly Medium Instant
Canary Gradual traffic shift (5%→50%→100%) Low Quick
Rolling Update Replace instances one by one Low Minutes
A/B Testing Split traffic by user segment Low N/A (experimental)

Example: Kubernetes Blue-Green deployment

# blue-deployment.yaml (current production)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-blue
  labels:
    app: frontend
    version: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
      version: blue
  template:
    metadata:
      labels:
        app: frontend
        version: blue
    spec:
      containers:
      - name: frontend
        image: myapp/frontend:v1.0.0
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"

---
# green-deployment.yaml (new version)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-green
  labels:
    app: frontend
    version: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: frontend
      version: green
  template:
    metadata:
      labels:
        app: frontend
        version: green
    spec:
      containers:
      - name: frontend
        image: myapp/frontend:v2.0.0  # New version
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"

---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  selector:
    app: frontend
    version: blue  # Initially pointing to blue
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: LoadBalancer

# Deployment process:
# 1. Deploy green version
kubectl apply -f green-deployment.yaml

# 2. Test green version internally
kubectl port-forward deployment/frontend-green 8080:80

# 3. Switch traffic to green (instant cutover)
kubectl patch service frontend-service -p '{"spec":{"selector":{"version":"green"}}}'

# 4. Monitor for issues
kubectl logs -f deployment/frontend-green

# 5. If issues, rollback to blue instantly
kubectl patch service frontend-service -p '{"spec":{"selector":{"version":"blue"}}}'

# 6. If successful, delete blue deployment
kubectl delete deployment frontend-blue

Example: Canary deployment with traffic splitting

# Using Istio for canary deployment

# virtual-service.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: frontend
spec:
  hosts:
  - frontend.example.com
  http:
  - match:
    - headers:
        canary:
          exact: "true"
    route:
    - destination:
        host: frontend
        subset: v2
  - route:
    - destination:
        host: frontend
        subset: v1
      weight: 95
    - destination:
        host: frontend
        subset: v2
      weight: 5  # 5% traffic to canary

---
# destination-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: frontend
spec:
  host: frontend
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

# Canary deployment script
#!/bin/bash

# Stage 1: Deploy v2 with 5% traffic
kubectl apply -f canary-deployment.yaml
kubectl apply -f virtual-service-5.yaml

# Wait and monitor
sleep 300

# Stage 2: Increase to 25%
kubectl apply -f virtual-service-25.yaml
sleep 300

# Stage 3: Increase to 50%
kubectl apply -f virtual-service-50.yaml
sleep 300

# Stage 4: Increase to 100%
kubectl apply -f virtual-service-100.yaml

# Remove old version
kubectl delete deployment frontend-v1

# Using Flagger for automated canary
# flagger-canary.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: frontend
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: frontend
  service:
    port: 80
  analysis:
    interval: 1m
    threshold: 10
    maxWeight: 50
    stepWeight: 5
    metrics:
    - name: request-success-rate
      thresholdRange:
        min: 99
      interval: 1m
    - name: request-duration
      thresholdRange:
        max: 500
      interval: 1m
  webhooks:
  - name: load-test
    url: http://flagger-loadtester/
    metadata:
      cmd: "hey -z 1m -q 10 -c 2 http://frontend-canary/"

Example: Vercel deployment with preview URLs

// Vercel automatic preview deployments
// Every PR gets a unique preview URL

// .github/workflows/preview.yml
name: Preview Deployment

on:
  pull_request:
    branches: [main]

jobs:
  deploy-preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID }}
          vercel-project-id: ${{ secrets.PROJECT_ID }}
          scope: ${{ secrets.VERCEL_SCOPE }}
      
      - name: Comment PR
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '🚀 Preview deployed to: https://my-app-pr-${{ github.event.number }}.vercel.app'
            })

// Netlify branch deploys
// netlify.toml
[context.deploy-preview]
  command = "npm run build"
  environment = { NODE_ENV = "staging" }

[context.branch-deploy]
  command = "npm run build"

# Each branch gets: https://branch-name--my-app.netlify.app
# Each PR gets: https://deploy-preview-123--my-app.netlify.app

// Progressive rollout with feature flags
import { useFeatureFlag } from '@/lib/feature-flags';

function NewFeature() {
  const isEnabled = useFeatureFlag('new-ui-redesign', {
    rollout: 10 // Start with 10% of users
  });
  
  if (!isEnabled) {
    return <OldFeature />;
  }
  
  return <RedesignedFeature />;
}

// Gradually increase rollout
// Day 1: 10%
// Day 3: 25%
// Day 7: 50%
// Day 14: 100%
Deployment Strategy Selection: Blue-Green for instant rollback with no downtime. Canary for gradual rollout with monitoring. Rolling update for resource-constrained environments. Always test in staging first.

6. Monitoring Sentry Performance Tracking

Implement comprehensive monitoring and error tracking to detect issues early and maintain application health in production.

Tool Purpose Key Features Pricing
Sentry Error tracking, performance Source maps, releases, alerts Free + paid tiers
Datadog Full observability APM, logs, metrics, traces $15+/host/month
New Relic Application monitoring Real user monitoring (RUM) Free + paid
LogRocket Session replay Video replay, console logs $99+/month
Google Analytics 4 User analytics Events, conversions, funnels Free

Example: Sentry integration with source maps

// Installation
npm install @sentry/nextjs

// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  environment: process.env.NODE_ENV,
  
  // Performance Monitoring
  tracesSampleRate: 1.0,
  
  // Session Replay
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  
  integrations: [
    new Sentry.BrowserTracing({
      tracePropagationTargets: [
        'localhost',
        /^https:\/\/api\.example\.com/
      ]
    }),
    new Sentry.Replay({
      maskAllText: true,
      blockAllMedia: true
    })
  ],
  
  // Filter sensitive data
  beforeSend(event, hint) {
    // Remove PII
    if (event.request) {
      delete event.request.cookies;
      delete event.request.headers;
    }
    
    // Ignore certain errors
    if (event.exception) {
      const error = hint.originalException;
      if (error && error.message?.includes('ResizeObserver')) {
        return null; // Don't send this error
      }
    }
    
    return event;
  }
});

// sentry.server.config.ts
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 1.0
});

// next.config.js - Source maps
const { withSentryConfig } = require('@sentry/nextjs');

module.exports = withSentryConfig(
  {
    // Your Next.js config
  },
  {
    silent: true,
    org: 'my-org',
    project: 'my-project',
    
    // Upload source maps
    authToken: process.env.SENTRY_AUTH_TOKEN,
    
    // Release tracking
    release: process.env.VERCEL_GIT_COMMIT_SHA,
    
    // Source map options
    widenClientFileUpload: true,
    hideSourceMaps: true,
    disableLogger: true
  }
);

// Usage in components
import * as Sentry from '@sentry/nextjs';

function MyComponent() {
  const handleError = () => {
    try {
      throw new Error('Something went wrong');
    } catch (error) {
      Sentry.captureException(error, {
        tags: {
          component: 'MyComponent',
          action: 'button-click'
        },
        extra: {
          userId: user.id,
          timestamp: Date.now()
        }
      });
    }
  };
  
  return <button onClick={handleError}>Trigger Error</button>;
}

Example: Custom performance monitoring

// lib/monitoring.ts
import * as Sentry from '@sentry/nextjs';

// Track custom metrics
export function trackMetric(name: string, value: number, tags?: Record<string, string>) {
  Sentry.metrics.gauge(name, value, {
    tags,
    unit: 'millisecond'
  });
}

// Track API performance
export async function monitoredFetch(url: string, options?: RequestInit) {
  const startTime = performance.now();
  const transaction = Sentry.startTransaction({
    name: `API ${options?.method || 'GET'} ${url}`,
    op: 'http.client'
  });
  
  try {
    const response = await fetch(url, options);
    const duration = performance.now() - startTime;
    
    // Track success
    trackMetric('api.response_time', duration, {
      endpoint: url,
      status: String(response.status),
      method: options?.method || 'GET'
    });
    
    if (!response.ok) {
      Sentry.captureMessage(`API Error: ${response.status} ${url}`, 'warning');
    }
    
    transaction.setHttpStatus(response.status);
    transaction.finish();
    
    return response;
  } catch (error) {
    const duration = performance.now() - startTime;
    
    // Track failure
    trackMetric('api.error_count', 1, {
      endpoint: url,
      error: error.message
    });
    
    Sentry.captureException(error, {
      tags: { endpoint: url },
      extra: { duration }
    });
    
    transaction.setStatus('internal_error');
    transaction.finish();
    
    throw error;
  }
}

// React Error Boundary with Sentry
import { ErrorBoundary } from '@sentry/nextjs';

function App() {
  return (
    <ErrorBoundary
      fallback={({ error, resetError }) => (
        <div>
          <h1>Something went wrong</h1>
          <p>{error.message}</p>
          <button onClick={resetError}>Try again</button>
        </div>
      )}
      showDialog
    >
      <YourApp />
    </ErrorBoundary>
  );
}

// Core Web Vitals tracking
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

function sendToAnalytics(metric) {
  // Send to Sentry
  Sentry.metrics.gauge(metric.name, metric.value, {
    tags: {
      rating: metric.rating
    },
    unit: metric.name === 'CLS' ? 'ratio' : 'millisecond'
  });
  
  // Send to Google Analytics
  gtag('event', metric.name, {
    value: Math.round(metric.value),
    metric_id: metric.id,
    metric_rating: metric.rating
  });
}

getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);

Example: Comprehensive monitoring dashboard setup

// Datadog RUM integration
import { datadogRum } from '@datadog/browser-rum';

datadogRum.init({
  applicationId: process.env.NEXT_PUBLIC_DD_APP_ID!,
  clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN!,
  site: 'datadoghq.com',
  service: 'my-app',
  env: process.env.NODE_ENV,
  version: process.env.NEXT_PUBLIC_APP_VERSION,
  
  sessionSampleRate: 100,
  sessionReplaySampleRate: 20,
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  
  defaultPrivacyLevel: 'mask-user-input'
});

// Custom monitoring service
class MonitoringService {
  private static instance: MonitoringService;
  
  private constructor() {
    this.initHealthChecks();
  }
  
  static getInstance() {
    if (!MonitoringService.instance) {
      MonitoringService.instance = new MonitoringService();
    }
    return MonitoringService.instance;
  }
  
  // Track page views
  trackPageView(page: string) {
    gtag('event', 'page_view', { page_path: page });
    Sentry.addBreadcrumb({
      category: 'navigation',
      message: `Navigated to ${page}`,
      level: 'info'
    });
  }
  
  // Track custom events
  trackEvent(name: string, properties?: Record<string, any>) {
    gtag('event', name, properties);
    Sentry.addBreadcrumb({
      category: 'user-action',
      message: name,
      data: properties,
      level: 'info'
    });
  }
  
  // Track errors
  trackError(error: Error, context?: Record<string, any>) {
    console.error(error);
    Sentry.captureException(error, {
      extra: context
    });
  }
  
  // Health checks
  private initHealthChecks() {
    setInterval(() => {
      this.checkApiHealth();
      this.checkPerformance();
    }, 60000); // Every minute
  }
  
  private async checkApiHealth() {
    try {
      const response = await fetch('/api/health');
      if (!response.ok) {
        this.trackError(new Error('API health check failed'), {
          status: response.status
        });
      }
    } catch (error) {
      this.trackError(error as Error, { check: 'api-health' });
    }
  }
  
  private checkPerformance() {
    const memory = (performance as any).memory;
    if (memory && memory.usedJSHeapSize > 100 * 1024 * 1024) {
      Sentry.captureMessage('High memory usage detected', {
        level: 'warning',
        extra: {
          usedHeapSize: memory.usedJSHeapSize,
          totalHeapSize: memory.totalJSHeapSize
        }
      });
    }
  }
}

export const monitoring = MonitoringService.getInstance();

// Usage
monitoring.trackEvent('button_click', { button: 'checkout' });
monitoring.trackError(new Error('Payment failed'), { amount: 99.99 });

Production Deployment Checklist

Category Task Priority Status
Hosting Configure CDN and caching High
Security Set up HTTPS and security headers Critical
Monitoring Integrate error tracking (Sentry) Critical
Performance Track Core Web Vitals High
CI/CD Automated deployment pipeline High
Config Environment variables properly set Critical
Deployment Blue-green or canary strategy Medium
Backup Rollback plan documented High