CI/CD que funciona, Docker com critério, Kubernetes quando faz sentido e FinOps embutido desde o início. DORA Metrics como bússola — não como vaidade de slide.
"Em TI, tudo é nivelado pelo mais lento. O alicerce precisa ser feito da melhor maneira possível desde o início."
— Cesar Zanis
01
DORA Metrics — as 4 que importam
Google pesquisou 30.000 profissionais por 6 anos. Essas 4 métricas diferenciam times Elite de times Low. Use como diagnóstico, não como meta de OKR.
Deployment Frequency
> 1x por dia (Elite)vs< 1x por mês (Low)
Por que importa
Frequência alta = lotes pequenos = menor risco por deploy. Time que deploya 1x por mês está acumulando risco, não sendo cuidadoso.
Como melhorar
Reduza o tamanho dos lotes. Feature flags para desacoplar deploy de release.
Lead Time for Changes
< 1 hora (Elite)vs> 6 meses (Low)
Por que importa
Tempo entre commit e produção. Longo = feedback lento = problemas descobertos tarde. Não é velocidade por velocidade — é ciclo de aprendizado.
Como melhorar
Automatize stages. Elimine aprovações manuais desnecessárias. Teste em PR, não depois do merge.
Change Failure Rate
< 5% (Elite)vs> 46% (Low)
Por que importa
Porcentagem de deploys que causam incidente. Alto = qualidade de teste ruim ou escopo de mudança grande demais.
Como melhorar
Testes automatizados com cobertura real (não decorativa). Blue/green deployment. Rollback em < 5 minutos.
MTTR (Mean Time to Restore)
< 1 hora (Elite)vs> 6 meses (Low)
Por que importa
Quanto tempo para restaurar serviço após incidente. Mais importante que não cair é saber voltar rápido.
Como melhorar
Runbooks documentados. Alertas com contexto (não só "CPU alta"). Post-mortem sem blame após cada SEV-1.
02
CI/CD — pipelines que funcionam
Pipeline mínimo que funciona (GitHub Actions)
YAML
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Cache de dependências — reduz tempo em 60-70%
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test -- --coverage
# Upload de coverage — visibilidade sem esforço
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
build:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
# Build e push da imagem Docker
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:latest
cache-from: type=gha # Cache de layer Docker entre runs
cache-to: type=gha,mode=max
Dockerfile multi-stage — a diferença entre 1.2GB e 120MB
YAML
# Dockerfile multi-stage
# Stage 1: Build — tem tudo que precisa para compilar
FROM node:20-alpine AS builder
WORKDIR /app
# Copiar só package.json primeiro — cache eficiente
# Se o código muda mas as dependências não, esta layer é reutilizada
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: Runtime — tem só o que precisa para rodar
FROM node:20-alpine AS runner
WORKDIR /app
# Usuário não-root — segurança básica
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Copiar apenas o output do build
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
USER nextjs
EXPOSE 3000
ENV PORT=3000 NODE_ENV=production
# Health check — o orquestrador sabe quando reiniciar
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
CMD wget -qO- http://localhost:3000/api/health || exit 1
CMD ["node", "server.js"]
# Resultado: imagem final ~120MB vs ~1.2GB sem multi-stage
03
FinOps — custo como feature, não como acidente
A maioria dos times descobre que está pagando 3x mais do que deveria quando chega a fatura do fim do mês. FinOps não é cortar custo — é gastar o certo no lugar certo.
01
Dimensione para o P90, não para o pico
A maioria das empresas superprovisionou para pico máximo que acontece 5% do tempo. Auto-scaling resolve o pico. Right-sizing resolve os outros 95%.
02
Spot/Preemptible para workloads sem estado
CI/CD, processamento em batch, workers de fila. Até 80% mais barato. A contrapartida é interrupção — design stateless absorve isso.
03
Reserved instances só para baseline comprovado
Reserve o que você tem certeza que vai usar. O risco de comprometer capacidade que você não usa supera o desconto em cenários de mudança rápida.
04
Tags de custo desde o início
Sem tags por serviço/time/ambiente, o billing vira uma caixa preta. Crie a política de tags antes de criar qualquer recurso. Retroagir é doloroso.
05
Budget alert antes de estourar, não depois
Configure alertas em 50%, 80% e 100% do budget. O alerta de 50% é o que importa — te dá tempo de agir sem urgência.
Kubernetes — o mais mal-aplicado da lista
K8s resolve problemas de orquestração em escala. Se você tem menos de 10 serviços, uma equipe de 5 pessoas e não está operando em múltiplos clouds simultaneamente, você provavelmente está adicionando complexidade sem justificativa.
Use quando: múltiplos serviços com ciclos de deploy independentes, necessidade de auto-scaling granular, equipe com experiência real em K8s.
Evite quando: monólito funcional, time pequeno, operação em cloud único, nenhum engenheiro de plataforma dedicado. Docker Compose + Cloud Run/ECS resolve 80% dos casos com 20% da complexidade.