System Design/02 - Componentes/Application Layer2 min
Microservices
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Dividir a aplicação em serviços pequenos, independentes e implantáveis separadamente, cada um dono do próprio dado e comunicando-se por rede.
| Monolito | Microserviços | |
|---|---|---|
| Deploy | Tudo junto | Independente por serviço |
| Escala | O sistema inteiro | Só o serviço gargalo |
| Falha | Derruba tudo | Isolada (se houver Bulkhead) |
| Tecnologia | Uma stack | Uma por serviço |
| Chamada interna | Função (ns) | Rede (ms), pode falhar |
| Transação | ACID do banco | Distribuída (Compensating Transaction) |
| Depuração | Stack trace | Tracing distribuído |
O critério de divisão
A fronteira certa é o domínio de negócio (bounded context), não a camada técnica. "Pedidos" e "Estoque" são divisões viáveis; "Controllers" e "DAOs" não — geram acoplamento em toda mudança.
Regra prática: se duas mudanças de negócio quase sempre atravessam a mesma fronteira, a fronteira está no lugar errado.
Cada serviço com o próprio banco
É o ponto mais custoso e mais importante. Compartilhar banco entre serviços recria o acoplamento que os microserviços deveriam remover — o schema vira uma API implícita que ninguém pode mudar.
O preço: acabam-se os JOIN entre domínios, e consultas que cruzam serviços exigem CQRS, Materialized View ou composição na aplicação.
Trade-offs
Microserviços trocam complexidade de código por complexidade operacional. Ganha-se deploy independente, isolamento de falha e escala granular; paga-se com latência de rede, consistência eventual, observabilidade distribuída e infraestrutura muito mais pesada.
O erro clássico é o monolito distribuído: serviços que não podem ser deployados sozinhos porque dependem sincronicamente uns dos outros. Fica-se com todo o custo distribuído e nenhum benefício de independência.
O conselho consolidado é monolito primeiro. As fronteiras corretas só ficam claras depois de o domínio amadurecer; extrair um serviço de um monolito bem modularizado é fácil, e unir microserviços mal divididos é caríssimo.
Exemplo prático
Um e-commerce em que o checkout precisa de 10x mais capacidade na Black Friday e o catálogo continua igual. Como monolito, escala-se tudo — desperdiçando capacidade em nove décimos do código.
Separado, escala-se só o checkout. O preço aparece na primeira falha: o checkout chama estoque, pagamento e frete por rede. Se pagamento fica lento, o checkout precisa de Circuit Breaker, timeout, Retry com backoff e Bulkhead — nada disso era necessário quando a chamada era uma função local.
Relacionado
Parte de Application Layer · roadmap.sh/system-design