Food trucks × um restaurante grande
Um restaurante grande tem uma cozinha só: um cardápio, um chef coordenando, tudo sob o mesmo teto — simples de operar, difícil de escalar uma parte sem mexer no resto. Uma praça de food trucks é o oposto: cada truck é autônomo, abre e fecha sozinho, tem sua própria fila e pode ser trocado sem afetar os outros. Mas agora alguém precisa coordenar estacionamento, energia, lixo e a praça inteira — a complexidade saiu de dentro da cozinha e foi para o espaço entre os trucks. Microsserviços são a praça: autonomia de cada truck, ao preço de operar a praça.
O que a rede cobra
O erro fundador é achar que microsserviços são 'o monólito, só que em pedaços'. Não são: no momento em que uma chamada de método vira uma chamada de rede, ela herda as 8 falácias — pode falhar, demorar, voltar diferente — e cada uma precisa de timeout, retry e tratamento de erro.
E a transação some. Dentro de um banco, 'cobrar e baixar estoque' é ACID. Entre dois serviços com bancos diferentes, não existe transação compartilhada: vira uma saga, com consistência eventual e ações de compensação para desfazer o que já foi feito.
A regra que dá autonomia de verdade é banco por serviço: cada serviço é dono do seu dado e ninguém acessa as tabelas do outro direto. Sem isso, você tem um 'monólito distribuído' — o pior dos dois mundos: os serviços estão separados fisicamente (com latência de rede e deploys a coordenar) mas acoplados pelos dados (uma mudança de schema quebra vários). A separação física sem a separação de dados só adiciona custo.
É por isso que microsserviços são, antes de tudo, uma decisão organizacional (Lei de Conway): a divisão só entrega o prometido se cada serviço tem um time dono, capaz de fazer deploy sozinho. Dividir o código em dez serviços mantendo um time único que mexe em tudo produz o monólito distribuído. O caminho saudável quase sempre começa por um monólito modular bem fronteirado — as fronteiras de módulo, já testadas dentro do processo, viram as fronteiras de serviço quando (e se) a escala ou a autonomia justificarem a distribuição.
Como isso aparece na prática
O serviço de checkout que precisava escalar sozinho
Cenário
Numa Black Friday, só o checkout ficava sob carga extrema, mas ele vivia no mesmo monólito que o catálogo e o painel administrativo. Escalar o checkout obrigava a subir réplicas do sistema inteiro, caro e lento.
Como o padrão entra
O checkout foi extraído para um serviço próprio, com deploy e escala independentes, comunicando-se com o resto por eventos. Nos picos, só ele sobe réplicas.
Trade-off: O fluxo de compra passou a atravessar a rede e virou uma saga, com consistência eventual entre checkout, estoque e pagamento. Foi o preço aceito para poder escalar a parte quente sem carregar o resto.
O monólito distribuído que ninguém conseguia deployar
Cenário
Um time dividiu o sistema em oito serviços, mas todos liam e escreviam no mesmo banco compartilhado. Uma mudança de schema quebrava vários serviços de uma vez, e os deploys tinham que ser coordenados como se ainda fosse um monólito — agora com latência de rede.
Como o padrão entra
Cada serviço passou a ser dono do seu próprio banco, e o acesso a dados de outro serviço virou chamada de API ou evento. As fronteiras de dados foram alinhadas às fronteiras de serviço.
Trade-off: Separar os bancos foi uma migração longa e cara, e o que era um JOIN virou chamada remota. Em troca, os serviços finalmente puderam ser desenvolvidos e implantados de forma independente.
Onde isto dá errado
Banco compartilhado entre serviços
Serviços que leem e escrevem nas mesmas tabelas estão acoplados pelo dado: uma mudança de schema quebra vários, e os deploys voltam a precisar de coordenação. É o monólito distribuído — custo de rede sem a autonomia.
Dividir cedo demais, com fronteiras incertas
No início, as fronteiras de domínio ainda estão se descobrindo. Congelá-las em serviços (com rede e banco separados) torna mover uma fronteira caríssimo — o que num monólito modular seria uma refatoração vira uma migração distribuída.
Ignorar a rede entre os serviços
Tratar chamada remota como local — sem timeout, sem retry, sem tratar falha parcial — faz o sistema desmoronar no primeiro soluço de rede. As 8 falácias não são opcionais quando há rede no meio.
Autonomia com a rede no meio
// Microsservicos: cada servico e autonomo — proprio deploy, proprio
// banco, propria escala. Eles se falam pela REDE, nao por chamada local.
// Servico de Pedidos NAO acessa a tabela de Estoque direto.
// Ele pede, pela rede, ao servico dono daquele dado:
const estoque = await fetch("http://estoque/itens/42").then((r) => r.json());
// ^^^^^ e aqui entram TODAS as 8 falacias da rede:
// pode falhar, demorar, voltar diferente.
// E a transacao que cruza servicos perde o ACID:
// "cobrar + baixar estoque" nao cabe numa transacao de banco unica.
// Vira uma SAGA: cada passo commita local, e uma falha compensa os anteriores.
// A autonomia (deploy e escala independentes) e o premio.
// A rede no meio e a consistencia eventual sao a conta.Quando usar × quando evitar
Use quando
3- Quando vários times precisam entregar sem travar uns aos outros.
- Quando partes do sistema têm perfis de escala muito diferentes.
- Quando as fronteiras de domínio já estão claras e estáveis.
Evite quando
2- No início de um produto, com time pequeno e fronteiras incertas.
- Quando um monólito modular ainda resolve.
Testar o que ficou
3 armadilhas de Microsserviços viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.
Onde isto aparece de verdade
Você já usa isto, talvez sem saber o nome.
Netflix, Amazon, UberAs arquiteturas de referência que popularizaram serviços pequenos e independentes, cada um com seu deploy e seu banco.um repositório e deploy por serviçoCada serviço com seu próprio ciclo de vida — build, deploy e escala independentes — é a marca operacional do estilo.banco por serviçoCada serviço dono do seu banco, sem outro acessando as tabelas dele direto, é o que dá a autonomia e cobra a consistência eventual.
O padrão em uma linha
Sem nome de domínio, sem cerimônia. Só a ideia.
// Deploy e banco por serviço — fronteira física.
// pedido-svc e estoque-svc não compartilham tabela.O que ele cobra
3 saltos a mais entre a chamada e o efeito.
- Cada serviço vira um sistema a operar: deploy, banco, monitoramento, alerta e plantão próprios
- Uma transação que atravessa serviços perde o ACID e vira saga, com consistência eventual e compensação
Não vale se: o sistema é pequeno e o time é um só — a complexidade distribuída custa muito mais do que a autonomia que ela compra.
Costuma ser confundido com
Onde isto aparece
Continue por aqui
- Monólito modularO meio-termo que a moda dos microsserviços fez esquecer: um único deploy, mas com módulos de fronteiras internas reais, cada um escondendo suas entranhas atrás de uma API pública. Dá a maior parte do benefício da modularização — responsabilidades separadas, mudanças isoladas — sem pagar a rede, a consistência eventual e o custo operacional de distribuir. Costuma ser o ponto de partida certo, e o destino final de muita gente.
- Lei de ConwaySistemas espelham a estrutura de comunicação de quem os constrói. Dois times que mal se falam produzem uma integração pobre entre seus módulos — não por falha técnica, mas por organograma. A consequência prática é poderosa: para obter a arquitetura que você quer, muitas vezes é preciso primeiro organizar os times na forma dessa arquitetura.
- SagaCoordena uma transação distribuída de longa duração como uma sequência de transações locais, cada uma com uma ação compensatória para desfazer semanticamente em caso de falha.