CI/CD & Deployment

Difficulty: Intermediate

Question

What is CI/CD? Describe a deployment pipeline you've worked with or would design.

Answer

CI (Continuous Integration): Automatically build and test code on every push. Catches bugs early.

CD (Continuous Delivery): Automatically prepare releases for deployment. Human approves.

CD (Continuous Deployment): Automatically deploy to production on every merge. No human step.

A good pipeline: Push → Lint → Test → Build → Deploy to staging → Manual approval → Deploy to production

Code examples

GitHub Actions CI Pipeline

# .github/workflows/ci.yml
name: CI Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: test
        ports:
          - 5432:5432
    
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      
      - run: npm ci
      - run: npm run lint
      - run: npm run typecheck
      - run: npm test -- --coverage
      - run: npm run build
      
      - uses: actions/upload-artifact@v4
        with:
          name: coverage
          path: coverage/

This pipeline runs on every push and PR: installs deps, lints, type-checks, tests with coverage, and builds. If any step fails, the PR can't be merged.

Deployment Strategies

// 1. Rolling Deployment
// Replace instances one at a time
// [v1] [v1] [v1] → [v2] [v1] [v1] → [v2] [v2] [v1] → [v2] [v2] [v2]
// Pro: zero downtime, gradual rollout
// Con: mix of versions temporarily

// 2. Blue-Green Deployment
// Blue (current) ← traffic
// Green (new)     ← deploy & test here
// Then switch: Green ← traffic
// If problems: switch back to Blue instantly
// Pro: instant rollback
// Con: needs 2x infrastructure

// 3. Canary Deployment
// Route 5% of traffic to new version
// Monitor errors, latency, business metrics
// If OK: gradually increase to 25% → 50% → 100%
// If problems: route all traffic back to old version
// Pro: catches issues with minimal user impact
// Con: complex routing logic

// 4. Feature Flags (not a deployment strategy, but related)
// Deploy code but control visibility
if (featureFlags.isEnabled('new-checkout', user)) {
  renderNewCheckout();
} else {
  renderOldCheckout();
}

Start with Blue-Green for simplicity and instant rollback. Move to Canary when you need more confidence in gradual rollouts.

Monitoring & Observability

// The 3 pillars of observability:

// 1. LOGGING (what happened)
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [new winston.transports.Console()],
});
logger.info('User logged in', { userId: 123, ip: '1.2.3.4' });
logger.error('Payment failed', { orderId: 456, error: err.message });

// 2. METRICS (how much / how fast)
// - Request rate (requests/second)
// - Error rate (% of 5xx responses)
// - Latency (p50, p95, p99 response times)
// - Saturation (CPU, memory, disk usage)
// Tools: Prometheus, Grafana, Datadog

// 3. TRACING (request flow across services)
// Track a request through: API Gateway → Auth → DB → Cache → Response
// Tools: Jaeger, Zipkin, OpenTelemetry

// Health check endpoint
app.get('/health', async (req, res) => {
  const dbOk = await checkDatabase();
  const cacheOk = await checkRedis();
  const status = dbOk && cacheOk ? 200 : 503;
  res.status(status).json({ db: dbOk, cache: cacheOk });
});

// Alerting rules:
// - Error rate > 1% for 5 minutes → warning
// - Error rate > 5% for 2 minutes → critical
// - p99 latency > 2s for 10 minutes → warning
// - Health check fails → critical

Good monitoring catches issues before users report them. The health endpoint is used by load balancers and Kubernetes to route traffic away from unhealthy instances.

Key points

Concepts covered

CI/CD, GitHub Actions, Testing Pipeline, Blue-Green Deploy, Monitoring