Twelve-Factor App - Principios de Design Cloud-Native

15 min leitura | 2025.12.11

O que e Twelve-Factor App

Twelve-Factor App sao 12 principios de design para construir aplicacoes web modernas, propostos por Adam Wiggins, cofundador do Heroku, em 2011. Eles permitem um design adequado para SaaS (Software as a Service) que opera em ambientes de nuvem.

Por que e importante: Em uma era onde containerizacao, microsservicos e CI/CD se tornaram comuns, estes principios sao a base do design de aplicacoes cloud-native.

Os 12 Principios

1. Codebase (Base de Codigo)

Uma base de codigo versionada, multiplos deploys.

flowchart LR
    Repo["Repositorio"] --> Dev["Ambiente de Desenvolvimento"]
    Repo --> Staging["Ambiente de Staging"]
    Repo --> Prod["Ambiente de Producao"]
  • X Repositorios diferentes por ambiente
  • X Multiplas aplicacoes em um repositorio

2. Dependencies (Dependencias)

Declarar e isolar dependencias explicitamente.

// package.json - Declaracao explicita de dependencias
{
  "dependencies": {
    "express": "^4.18.0",
    "pg": "^8.10.0"
  }
}
# Nao depender de pacotes instalados globalmente no sistema
X Depender de imagemagick global
O Instalar explicitamente no Dockerfile

3. Config (Configuracao)

Armazenar configuracao em variaveis de ambiente.

// X Exemplo ruim: Configuracao hardcoded no codigo
const dbHost = 'localhost';

// O Exemplo bom: Obter de variavel de ambiente
const dbHost = process.env.DATABASE_HOST;
# Configurar via variaveis de ambiente
DATABASE_HOST=db.example.com
DATABASE_USER=admin
API_KEY=secret123

4. Backing Services (Servicos de Apoio)

Tratar servicos de apoio (DB, cache, filas, etc.) como recursos anexados.

flowchart LR
    App["Aplicacao"] --> DB["PostgreSQL<br/>(local ou Amazon RDS)"]
    App --> Cache["Redis<br/>(local ou ElastiCache)"]
    App --> Storage["S3<br/>(armazenamento externo)"]

Migracao possivel apenas trocando a variavel de ambiente

5. Build, Release, Run (Construir, Publicar, Executar)

Separar rigorosamente os tres estagios: build, release e run.

flowchart LR
    Code["Codigo"] --> Build["Build"]
    Build --> Artifact["Artefato<br/>Executavel"]
    Config["Configuracao"] --> Release["Release<br/>Versao"]
    Artifact --> Release
    Release --> Run["Processo<br/>em Execucao"]

X Editar codigo diretamente em producao O Fazer deploy de uma nova release

6. Processes (Processos)

Executar a aplicacao como um ou mais processos stateless.

// X Exemplo ruim: Armazenar sessao em memoria
const sessions = {};
app.use((req, res, next) => {
  sessions[req.sessionId] = req.user;
});

// O Exemplo bom: Usar store externo
const RedisStore = require('connect-redis');
app.use(session({
  store: new RedisStore({ client: redisClient })
}));

7. Port Binding (Vinculacao de Porta)

Exportar servicos via vinculacao de porta.

// A propria aplicacao se torna o servidor web
const express = require('express');
const app = express();

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

8. Concurrency (Concorrencia)

Escalar horizontalmente atraves do modelo de processos.

Web     [X] [X] [X] [X]     <- 4 processos
Worker  [X] [X]             <- 2 processos
Clock   [X]                 <- 1 processo

-> Ajustar numero de processos conforme a carga

9. Disposability (Descartabilidade)

Maximizar robustez com inicializacao rapida e shutdown gracioso.

// Shutdown gracioso
process.on('SIGTERM', async () => {
  console.log('SIGTERM received, shutting down gracefully');

  // Parar de aceitar novas requisicoes
  server.close();

  // Completar requisicoes em andamento
  await finishPendingRequests();

  // Fechar conexao com banco de dados
  await db.close();

  process.exit(0);
});

10. Dev/Prod Parity (Paridade Dev/Prod)

Manter desenvolvimento, staging e producao o mais similares possivel.

GapTradicionalTwelve-Factor
TempoSemanas a mesesHoras a dias
ResponsavelDesenvolvedores e operadores separadosMesma pessoa faz deploy
FerramentasSQLite em dev, PostgreSQL em prodUsar mesmo servico
# docker-compose.yml - Usar mesmo DB em desenvolvimento e producao
services:
  db:
    image: postgres:15
  redis:
    image: redis:7

11. Logs

Tratar logs como fluxos de eventos.

// X Exemplo ruim: Escrever em arquivo
fs.appendFileSync('/var/log/app.log', message);

// O Exemplo bom: Saida para stdout
console.log(JSON.stringify({
  timestamp: new Date().toISOString(),
  level: 'info',
  message: 'User logged in',
  userId: '123'
}));
# Logs sao coletados e agregados externamente
docker logs app | fluentd

12. Admin Processes (Processos Administrativos)

Executar tarefas administrativas como processos unicos.

# Migracao
npx prisma migrate deploy

# Script de correcao de dados
node scripts/fix-data.js

# Debug com REPL
node --inspect app.js

Pontos Praticos

Compatibilidade com Docker

# Dockerfile compativel com Twelve-Factor
FROM node:20-slim

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production  # 2. Dependencias

COPY . .

# 7. Vinculacao de Porta
EXPOSE 3000

# 6. Processo Stateless
CMD ["node", "server.js"]

Combinacao com Kubernetes

# ConfigMap para gerenciar configuracao (3. Configuracao)
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  NODE_ENV: production

# Deployment para escala (8. Concorrencia)
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 3

Resumo

Os principios do Twelve-Factor App sao a base do pensamento para desenvolvimento de aplicacoes cloud-native. Seguindo estes principios, voce pode construir aplicacoes escalaveis, de facil manutencao e portaveis. Nao e necessario aplicar tudo de uma vez; recomendamos adota-los gradualmente conforme a situacao do projeto.

← Voltar para a lista