DevOps — Infrastructure & Deployment
Ship reliably. Monitor everything. Fix fast.
Deployment Checklist
Before any deploy:
- All tests pass in CI (not just locally)
- Environment variables set in target environment
- Database migrations tested against production-like data
- Rollback plan documented (even if it's "revert this commit")
- Health check endpoint exists and returns 200
CI/CD Pipeline
push → lint → typecheck → test → build → deploy staging → smoke test → deploy prod
| Stage |
Fails? |
Action |
| Lint/Types |
Block merge |
Fix locally |
| Tests |
Block merge |
Fix or update tests |
| Build |
Block merge |
Fix build errors |
| Staging deploy |
Block prod |
Debug in staging |
| Smoke test |
Block prod |
Rollback staging, investigate |
| Prod deploy |
Alert on-call |
Rollback immediately |
Docker
Always use multi-stage builds to keep images small. Detect the stack and use the appropriate base image.
Node.js / TypeScript
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]
Python
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Go
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/api
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]
Ruby on Rails
FROM ruby:3.3-slim AS builder
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle install --without development test
FROM ruby:3.3-slim
WORKDIR /app
COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . .
EXPOSE 3000
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
For other stacks (Java/JVM, .NET, Rust): same pattern — build stage compiles, final stage is minimal. Never copy the build toolchain into the final image.
Rules for all stacks:
- Always pin base image versions (not
latest)
- Use
.dockerignore — never ship build artifacts, .git, or .env files
- One process per container
- Add a health check:
HEALTHCHECK CMD curl -f http://localhost:<PORT>/health || exit 1
Monitoring
| What |
Tool Options |
Alert When |
| Uptime |
UptimeRobot, Checkly |
Down > 30 seconds |
| Errors |
Sentry, Datadog |
Error rate > 1% |
| Latency |
Grafana, Datadog |
p95 > 2 seconds |
| Resources |
Cloud provider metrics |
CPU > 80%, memory > 85% |
| Logs |
Datadog, Axiom, CloudWatch |
Error patterns, keywords |
Rules:
- Every alert must have a runbook (even a one-liner)
- If an alert fires and needs no action, delete it — alert fatigue kills
- Log structured JSON, not printf strings
- Include request ID in every log line for tracing
Infrastructure Defaults
| Decision |
Default |
Why |
| Hosting |
Vercel / Railway / Fly.io |
Zero-config, scales |
| Database |
Managed Postgres (Supabase, Neon, RDS) |
Don't manage your own DB |
| Cache |
Upstash Redis |
Serverless, no ops |
| Queue |
Inngest, Trigger.dev, or SQS |
Managed, retries built-in |
| Storage |
S3 / R2 / Supabase Storage |
Cheap, reliable |
| DNS |
Cloudflare |
Fast, free tier |
| Secrets |
Environment variables via platform |
Never in code or git |
Incident Response
- Detect — alert fires or user report
- Acknowledge — someone owns it (within 5 min)
- Mitigate — rollback, feature flag off, or scale up (fix the bleeding)
- Investigate — root cause after bleeding stops
- Fix — proper fix with tests
- Postmortem — blameless, focus on systems not people
1---2name: devops3description: (forwward) Configures CI/CD pipelines, Docker, monitoring, alerting, and infrastructure with reliability-first defaults. Triggers on CI/CD, Docker, deployment, monitoring, alerting, infrastructure setup, or production debugging.4---56# DevOps — Infrastructure & Deployment78Ship reliably. Monitor everything. Fix fast.910## Deployment Checklist1112Before any deploy:13141. All tests pass in CI (not just locally)152. Environment variables set in target environment163. Database migrations tested against production-like data174. Rollback plan documented (even if it's "revert this commit")185. Health check endpoint exists and returns 2001920## CI/CD Pipeline2122```23push → lint → typecheck → test → build → deploy staging → smoke test → deploy prod24```2526| Stage | Fails? | Action |27|-------|--------|--------|28| Lint/Types | Block merge | Fix locally |29| Tests | Block merge | Fix or update tests |30| Build | Block merge | Fix build errors |31| Staging deploy | Block prod | Debug in staging |32| Smoke test | Block prod | Rollback staging, investigate |33| Prod deploy | Alert on-call | Rollback immediately |3435## Docker3637Always use multi-stage builds to keep images small. Detect the stack and use the appropriate base image.3839### Node.js / TypeScript40```dockerfile41FROM node:22-alpine AS builder42WORKDIR /app43COPY package*.json ./44RUN npm ci --production=false45COPY . .46RUN npm run build4748FROM node:22-alpine49WORKDIR /app50COPY --from=builder /app/dist ./dist51COPY --from=builder /app/node_modules ./node_modules52EXPOSE 300053CMD ["node", "dist/server.js"]54```5556### Python57```dockerfile58FROM python:3.12-slim AS builder59WORKDIR /app60COPY requirements.txt .61RUN pip install --no-cache-dir -r requirements.txt6263FROM python:3.12-slim64WORKDIR /app65COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages66COPY . .67EXPOSE 800068CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]69```7071### Go72```dockerfile73FROM golang:1.22-alpine AS builder74WORKDIR /app75COPY go.mod go.sum ./76RUN go mod download77COPY . .78RUN CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/api7980FROM alpine:3.1981WORKDIR /app82COPY --from=builder /app/server .83EXPOSE 808084CMD ["./server"]85```8687### Ruby on Rails88```dockerfile89FROM ruby:3.3-slim AS builder90WORKDIR /app91COPY Gemfile Gemfile.lock ./92RUN bundle install --without development test9394FROM ruby:3.3-slim95WORKDIR /app96COPY --from=builder /usr/local/bundle /usr/local/bundle97COPY . .98EXPOSE 300099CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]100```101102For other stacks (Java/JVM, .NET, Rust): same pattern — build stage compiles, final stage is minimal. Never copy the build toolchain into the final image.103104**Rules for all stacks:**105- Always pin base image versions (not `latest`)106- Use `.dockerignore` — never ship build artifacts, `.git`, or `.env` files107- One process per container108- Add a health check: `HEALTHCHECK CMD curl -f http://localhost:<PORT>/health || exit 1`109110## Monitoring111112| What | Tool Options | Alert When |113|------|-------------|------------|114| Uptime | UptimeRobot, Checkly | Down > 30 seconds |115| Errors | Sentry, Datadog | Error rate > 1% |116| Latency | Grafana, Datadog | p95 > 2 seconds |117| Resources | Cloud provider metrics | CPU > 80%, memory > 85% |118| Logs | Datadog, Axiom, CloudWatch | Error patterns, keywords |119120**Rules:**121- Every alert must have a runbook (even a one-liner)122- If an alert fires and needs no action, delete it — alert fatigue kills123- Log structured JSON, not printf strings124- Include request ID in every log line for tracing125126## Infrastructure Defaults127128| Decision | Default | Why |129|----------|---------|-----|130| Hosting | Vercel / Railway / Fly.io | Zero-config, scales |131| Database | Managed Postgres (Supabase, Neon, RDS) | Don't manage your own DB |132| Cache | Upstash Redis | Serverless, no ops |133| Queue | Inngest, Trigger.dev, or SQS | Managed, retries built-in |134| Storage | S3 / R2 / Supabase Storage | Cheap, reliable |135| DNS | Cloudflare | Fast, free tier |136| Secrets | Environment variables via platform | Never in code or git |137138## Incident Response1391401. **Detect** — alert fires or user report1412. **Acknowledge** — someone owns it (within 5 min)1423. **Mitigate** — rollback, feature flag off, or scale up (fix the bleeding)1434. **Investigate** — root cause after bleeding stops1445. **Fix** — proper fix with tests1456. **Postmortem** — blameless, focus on systems not people