BMAD-METHOD/expansion-packs/javascript-fullstack-pack/data/deployment-strategies.md

5.9 KiB

Deployment Strategies for JavaScript Applications

Deployment Patterns

1. Rolling Deployment

How it works: Gradually replace old instances with new ones

Pros:

  • Simple to implement
  • No additional infrastructure needed
  • Zero downtime

Cons:

  • During deployment, old and new versions run simultaneously
  • Rollback requires another deployment

Best for: Most applications, default choice

2. Blue-Green Deployment

How it works: Two identical environments, switch traffic between them

Pros:

  • Instant rollback (switch back)
  • Test new version before switching
  • Zero downtime

Cons:

  • Double infrastructure cost during deployment
  • Database migrations can be tricky

Best for: Critical applications needing instant rollback

3. Canary Deployment

How it works: Route small % of traffic to new version, gradually increase

Pros:

  • Test with real users safely
  • Early problem detection
  • Gradual rollout reduces risk

Cons:

  • Complex routing logic
  • Need good monitoring
  • Longer deployment time

Best for: High-risk changes, large user bases

Platform-Specific Deployment

# Install Vercel CLI
npm i -g vercel

# Deploy
vercel --prod

# Environment variables
vercel env add DATABASE_URL production

Features:

  • Automatic HTTPS
  • Global CDN
  • Preview deployments for PRs
  • Zero-config for Next.js
  • Serverless functions

Railway (Backend/Full-stack)

# Install Railway CLI
npm i -g @railway/cli

# Login and init
railway login
railway init

# Deploy
railway up

Features:

  • PostgreSQL, Redis, MongoDB
  • Environment variables
  • Automatic SSL
  • GitHub integration

Docker + Fly.io

# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
CMD ["npm", "start"]
# Deploy
fly launch
fly deploy

AWS (EC2/ECS/Fargate)

  • Most flexible
  • Complex setup
  • Full control
  • Higher costs

DigitalOcean App Platform

  • Simple like Heroku
  • Reasonable pricing
  • Good for full-stack apps

CI/CD Setup

GitHub Actions

.github/workflows/deploy.yml:

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 18
      - run: npm ci
      - run: npm test
      - run: npm run build

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy to Vercel
        run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}

Database Migrations

Strategy 1: Migrations Before Deployment

# Run migrations before deploying new code
npm run db:migrate
npm run deploy

Pros: Safer, new code expects new schema

Cons: Brief downtime if migration is slow

Strategy 2: Backward-Compatible Migrations

# 1. Deploy code that works with old and new schema
# 2. Run migration
# 3. Deploy code that uses new schema only

Pros: Zero downtime

Cons: More complex, requires multiple deploys

Prisma Migrations

# Generate migration
npx prisma migrate dev --name add_user_role

# Apply in production
npx prisma migrate deploy

Environment Management

Environments

  • Development: Local machine
  • Staging: Pre-production testing
  • Production: Live application

Environment Variables

# Development (.env.local)
DATABASE_URL=postgresql://localhost:5432/dev
NEXT_PUBLIC_API_URL=http://localhost:3000

# Staging
DATABASE_URL=postgresql://staging.db/app
NEXT_PUBLIC_API_URL=https://staging.app.com

# Production
DATABASE_URL=postgresql://prod.db/app
NEXT_PUBLIC_API_URL=https://app.com

Rollback Strategies

1. Git Revert + Redeploy

git revert HEAD
git push origin main
# Triggers new deployment

2. Previous Build Rollback

Most platforms keep previous builds:

# Vercel
vercel rollback

# Railway
railway rollback

# Fly.io
fly releases
fly deploy --image <previous-image>

3. Blue-Green Switch Back

If using blue-green, switch traffic back to previous environment

Health Checks

// /api/health endpoint
app.get('/health', async (req, res) => {
  try {
    // Check database
    await prisma.$queryRaw`SELECT 1`;

    // Check Redis
    await redis.ping();

    res.json({ status: 'healthy' });
  } catch (error) {
    res.status(503).json({ status: 'unhealthy', error });
  }
});

Monitoring Post-Deployment

Metrics to Watch

  • Error rate
  • Response time (p50, p95, p99)
  • CPU/Memory usage
  • Database connection pool
  • API endpoint latencies

Tools

  • Sentry: Error tracking
  • Datadog: Full APM
  • Vercel Analytics: Frontend vitals
  • PostHog: Product analytics
  • Uptime Robot: Uptime monitoring

Deployment Checklist

Pre-Deployment

  • All tests pass locally and in CI
  • Code reviewed and approved
  • Database migrations tested on staging
  • Environment variables configured
  • Rollback plan ready
  • Team notified of deployment

During Deployment

  • Monitor error rates
  • Check health endpoints
  • Verify critical user flows
  • Watch application metrics

Post-Deployment

  • Smoke test production
  • Check error tracking (Sentry)
  • Monitor for 24 hours
  • Update changelog
  • Mark deployment as successful

Common Issues & Solutions

Issue: Database connection pool exhausted

Solution: Increase pool size or implement connection pooling middleware

Issue: Cold starts in serverless

Solution: Use provisioned concurrency or switch to container-based hosting

Issue: Build failing in CI

Solution: Ensure all dependencies in package.json, check environment variables

Issue: Rollback needed

Solution: Use platform-specific rollback or git revert + redeploy