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.
| Gap | Tradicional | Twelve-Factor |
|---|---|---|
| Tempo | Semanas a meses | Horas a dias |
| Responsavel | Desenvolvedores e operadores separados | Mesma pessoa faz deploy |
| Ferramentas | SQLite em dev, PostgreSQL em prod | Usar 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