O erro de arquitetura que quase todo projeto comete cedo demais

Tem vídeo desse conteúdo no canal Veja o passo a passo completo em vídeo.
Assistir no YouTube →
O erro de arquitetura que quase todo projeto comete cedo demais

Tem um momento na vida de quase todo projeto em que alguém desenha três caixinhas num quadro branco, liga elas com setas e diz: “vamos quebrar isso em microserviços”. Soa maduro. Soa escalável. E, na maioria das vezes, é cedo demais.

Não é que microserviços sejam ruins. O problema é adotá-los para resolver um problema que você ainda não tem — e, no caminho, criar um monte de problemas novos que você definitivamente não precisava.

O que a gente acha que está comprando

A promessa é sedutora: times independentes, deploys separados, cada serviço escalando no seu próprio ritmo. Você lê sobre a Netflix, sobre a Amazon, e imagina o seu sistema com a mesma elegância distribuída.

O detalhe que costuma passar batido é que essas empresas migraram para microserviços depois de terem centenas de engenheiros, dezenas de times e uma dor real de coordenação. Elas não começaram assim. Elas chegaram lá porque o monolito tinha virado um gargalo organizacional — não técnico.

O que a gente realmente leva

Quando você separa um sistema pequeno em vários serviços cedo demais, uma chamada de função que antes era instantânea e confiável vira uma chamada de rede. E rede falha. Fica lenta. Cai no meio. Aquele usuario.getEndereco() que nunca deu problema agora precisa de timeout, retry, tratamento de erro e, se você for honesto, um plano para quando o outro serviço simplesmente não responder.

Some a isso o que ninguém coloca no slide:

  • Transações distribuídas. Aquilo que era um BEGIN ... COMMIT agora é uma dança de eventos e compensações para manter os dados consistentes entre serviços.
  • Observabilidade. Um bug que atravessa cinco serviços exige rastreamento distribuído para você sequer entender por onde a requisição passou.
  • Ambiente local. Rodar o sistema inteiro na sua máquina deixa de ser um run e vira um exercício de orquestração.
  • Versionamento de contratos. Mudar o formato de um dado deixa de ser um refactor e passa a ser uma negociação entre serviços que não podem quebrar ao mesmo tempo.

Nada disso é impossível. Mas é custo. E custo que você paga todo santo dia, mesmo nos meses em que o sistema poderia estar simplesmente entregando valor.

A pergunta que quase ninguém faz

Antes de separar qualquer coisa, vale responder com sinceridade: qual problema isso resolve hoje?

Se a resposta for “escala”, pergunte quantas requisições por segundo você realmente tem — e não quantas você sonha em ter. Um monolito bem escrito, rodando em uma máquina decente, aguenta muito mais tráfego do que a maioria das aplicações jamais vai ver. Escala vertical é chata, mas é barata e simples.

Se a resposta for “os times estão se atropelando no mesmo código”, aí sim você está falando de um problema que microserviços resolvem. Só que, veja bem, esse é um problema de gente, não de tecnologia. E a maioria dos projetos que corre para microserviços não tem gente suficiente para justificar a divisão.

Microserviços são uma solução para um problema organizacional, com efeitos colaterais técnicos. Não o contrário.

O caminho do meio que costuma funcionar

Existe uma abordagem que envelhece bem: comece com um monolito, mas escreva ele com fronteiras claras por dentro. Módulos bem separados, cada um dono do seu domínio, conversando por interfaces explícitas em vez de mexerem nas tabelas uns dos outros.

Isso costuma ser chamado de “monolito modular”. A grande vantagem é que, no dia em que uma dessas fronteiras realmente precisar virar um serviço separado — por escala ou por time —, a costura já está desenhada. Você extrai o módulo em vez de arrancar código emaranhado de dentro de uma bola de lama.

Na prática, você ganha quase todos os benefícios de organização de código sem pagar o preço da rede, da consistência distribuída e da dor operacional. E adia a decisão cara para quando tiver dados reais para tomá-la.

Um exemplo que se repete

O padrão mais comum é quase uma comédia de erros. Um time de quatro pessoas divide o sistema em oito serviços “para já nascer escalável”. Seis meses depois, ninguém consegue rodar tudo na própria máquina, um deploy simples envolve coordenar três repositórios, e uma feature que tocaria duas telas agora exige mudança em quatro serviços e um contrato novo entre eles.

O detalhe cruel é que o tráfego, nesse meio-tempo, nunca chegou nem perto de justificar a separação. A escala que motivou tudo era hipotética. A complexidade que ela trouxe, essa era bem real — e cobrada todo santo dia. Quando finalmente pararam para medir, um único processo bem organizado daria conta com folga do volume que tinham.

Em vez de perguntar “como dividir”, pergunte “preciso dividir”

Arquitetura boa não é a mais sofisticada — é a mais adequada ao tamanho do problema. Adotar microserviços em um projeto de três pessoas é como comprar um caminhão para levar a marmita para o trabalho: tecnicamente carrega, mas você vai gastar mais tempo estacionando do que almoçando.

Quando a dor de coordenação chegar de verdade, você vai sentir. Ela tem cara de conflito de merge constante, de deploys que travam por causa de outro time, de gente com medo de mexer numa parte do código. Aí, sim, vale conversar sobre separar. Até lá, um monolito organizado é quase sempre a decisão de engenharia mais madura que você pode tomar.

Leia também

Prefere ver em vídeo?

Esse artigo virou um vídeo completo no canal, com diagramas animados e demo ao vivo.

Assistir no YouTube →