A era do “arrependimento dos microsserviços”: por que times estão voltando discretamente aos monólitos
6 min de leitura

A era do “arrependimento dos microsserviços”: por que times estão voltando discretamente aos monólitos

Por que startups e times de engenharia estão voltando aos monólitos modulares depois de sentir os custos operacionais e a complexidade dos microsserviços prematuros.

Começar a ler

Por um tempo, os microsserviços pareciam o próximo passo óbvio para qualquer produto de software sério.

Bastava uma startup começar a crescer para a conversa sobre arquitetura, mais cedo ou mais tarde, chegar na ideia de quebrar a aplicação em serviços menores. A autenticação virava um serviço próprio. Os pagamentos eram separados. As notificações iam para outro lugar. Em pouco tempo, um produto que começou como uma aplicação relativamente simples podia acabar com um número surpreendente de serviços rodando por trás.

E, sinceramente, havia bons motivos para fazer isso.

Microsserviços resolvem problemas reais. Eles permitem que os times façam deploy de partes do sistema de forma independente, escalem cargas específicas sem escalar todo o resto e deem a times de engenharia maiores mais autonomia sobre diferentes partes do produto.

Para empresas que operam em grande escala, essa separação pode ser extremamente útil.

O problema começa quando a arquitetura chega antes do problema.

Uma startup de cinco pessoas com alguns milhares de usuários não tem as mesmas necessidades de arquitetura que uma empresa com centenas de engenheiros e milhões de requisições por dia. Mesmo assim, é surpreendentemente fácil construir o produto menor como se esse futuro já tivesse chegado.

É aí que começa o arrependimento dos microsserviços.

O problema não são os microsserviços

Vale deixar uma coisa clara: este texto não é contra microsserviços.

Eles não são ruins. Na situação certa, são extremamente úteis.

O problema é adotá-los só porque parecem o jeito “certo” de construir uma aplicação moderna, e não porque o produto realmente precisa deles.

Imagine uma aplicação pequena com autenticação, pagamentos, perfis de usuário e notificações.

Você poderia transformar cada uma dessas partes em um serviço próprio. Num diagrama de arquitetura, isso pode parecer limpo e bem organizado.

Mas agora cada serviço precisa de um processo de deploy, monitoramento, logs, configuração, autenticação, tratamento de erros e documentação.

O que poderia ser uma chamada de função dentro da mesma aplicação agora é uma requisição de rede.

E requisições de rede podem falhar.

Um serviço pode dar timeout. Um banco de dados pode ficar indisponível por um tempo. Uma requisição pode ser repetida. Um serviço pode subir uma mudança antes de outro estar pronto para ela. De repente, você está lidando com problemas de sistemas distribuídos que simplesmente não existiam quando tudo morava dentro de uma única aplicação.

O produto não ficou necessariamente mais complicado.

A arquitetura ficou.

O custo escondido de ser “escalável”

Quando as pessoas falam de escalabilidade, normalmente estão falando de tráfego.

O sistema aguenta dez vezes mais usuários? Consegue processar mais requisições? Dá para escalar uma parte específica da aplicação de forma independente?

Essas são perguntas importantes, mas existe outro tipo de escalabilidade que é fácil de esquecer: o quanto o próprio time consegue entender e mudar o sistema.

Um sistema que aguenta milhões de requisições, mas exige três dias de estudo antes de qualquer mudança pequena, não é exatamente fácil de trabalhar.

Esse é um dos motivos pelos quais o monólito modular voltou a parecer atraente.

Em vez de quebrar tudo logo de cara em serviços independentes, o time pode manter uma única aplicação e, ainda assim, ter limites claros dentro dela. Autenticação, cobrança, usuários, notificações e outros domínios podem ter seus próprios módulos e responsabilidades sem exigir um serviço e uma infraestrutura separados para cada um.

Você ganha estrutura sem pagar de cara todo o custo operacional dos sistemas distribuídos.

E, se um desses módulos um dia ficar grande o bastante para justificar virar um serviço separado, dá para extraí-lo depois.

Essa flexibilidade faz diferença.

Experimente agora

Crie capturas de tela prontas para as lojas em minutos — grátis, sem marca d'água na exportação.

Você começa a usar o Launch Shots de graça. Todos os modelos (110+), mais de 220 molduras de dispositivo e mockups 3D, tradução por IA e upload direto para o App Store Connect e o Google Play Console. Sem cartão de crédito.

Começar grátis →

Você não precisa prever o futuro

Um dos jeitos mais fáceis de complicar demais a engenharia de uma startup é construir em torno de problemas que ainda não aconteceram.

“Talvez a gente tenha milhões de usuários.”

“Talvez a gente tenha vários times de engenharia.”

“Talvez a gente precise escalar esse componente de forma independente.”

“Talvez a gente troque de banco de dados depois.”

Tudo isso é possível.

Mas possível não quer dizer provável, e provável não quer dizer que você precisa resolver isso hoje.

A arquitetura de uma startup deveria responder principalmente aos problemas que o time está vivendo de verdade, e não a uma versão imaginária da empresa daqui a cinco anos.

Se um dia o sistema precisar ser dividido, você pode dividi-lo quando o motivo ficar claro.

Até lá, manter as coisas juntas pode deixar o desenvolvimento mais rápido, a depuração mais fácil e o sistema inteiro mais fácil de entender.

Isso não significa ignorar o crescimento futuro.

Significa aceitar que você provavelmente ainda não sabe exatamente como esse crescimento vai ser.

E tudo bem.

Cada serviço cria mais uma responsabilidade

É fácil olhar para uma arquitetura de microsserviços e ver um conjunto de peças pequenas e bem separadas.

O que passa despercebido é que cada uma dessas peças vem com um custo operacional.

Um serviço precisa de deploy. Precisa de monitoramento. Precisa de logs. Precisa de alertas. Precisa de configuração. Alguém precisa entender o que acontece quando ele cai. Alguém precisa investigar quando a latência dele sobe do nada.

Agora imagine fazer isso para dez serviços.

Depois vinte.

Depois cinquenta.

Para uma organização grande, essa sobrecarga pode valer muito a pena. A independência entre times e sistemas pode trazer valor suficiente para justificar toda essa complexidade.

Para um time pequeno, porém, isso pode virar uma distração.

Em vez de passar o tempo melhorando o produto, os desenvolvedores podem acabar gastando uma boa parte do tempo mantendo a engrenagem necessária para a arquitetura continuar de pé.

E esse é um dos custos menos óbvios dos microsserviços.

O código em si pode nem ser tão difícil.

É tudo o que existe em volta do código que começa a pesar.

O monólito modular merece mais respeito

O monólito modular fica em algum lugar entre os dois extremos.

Ele continua sendo uma única aplicação, mas não precisa ser uma base de código gigante e embolada em que tudo acessa tudo.

A aplicação pode ser dividida em módulos lógicos, com responsabilidades e limites claros.

Isso significa que os desenvolvedores podem pensar em domínios separados sem colocar uma fronteira de rede entre cada um deles.

O desenvolvimento também pode continuar relativamente simples. Rodar a aplicação localmente é mais fácil. Depurar costuma ser mais direto. As transações podem ser mais fáceis de gerenciar. O deploy não exige coordenar um monte de serviços independentes.

E há menos infraestrutura para manter.

Mais importante: começar com um monólito não significa ficar preso a ele para sempre.

Um monólito bem estruturado pode até facilitar uma migração futura para microsserviços, porque os limites já existem.

Se um dia o módulo de cobrança virar a parte do sistema que realmente precisa escalar ou ter deploy independente, você pode extraí-lo.

Você não precisa extrair tudo só porque uma parte precisa mudar.

Essa é a verdadeira vantagem de desenhar bons limites.

Você está criando opções para si mesmo.

Então, quando os microsserviços fazem sentido de verdade?

Não existe um número mágico de usuários a partir do qual uma empresa deveria trocar de repente um monólito por microsserviços.

Só o tráfego não basta para tomar essa decisão.

Os microsserviços ficam bem mais convincentes quando diferentes partes do sistema têm necessidades de escala realmente diferentes, quando os times precisam fazer deploy de forma independente, quando os limites entre domínios estão bem entendidos ou quando certos componentes exigem tecnologias ou infraestruturas completamente diferentes.

A estrutura do time também importa.

Uma organização com dezenas de times de engenharia tem problemas de coordenação muito diferentes dos de uma startup com quatro desenvolvedores.

A arquitetura deveria responder a essas realidades.

Se você está separando um serviço porque um componente está causando um problema real de escala, isso é um motivo.

Se você está separando um domínio porque vários times precisam trabalhar nele de forma independente, isso é um motivo.

Se você está fazendo isso porque “talvez a gente precise um dia”, talvez valha a pena esperar.

A melhor decisão de arquitetura costuma ser a que resolve o problema de hoje sem criar outros cinco.

A arquitetura mais sofisticada talvez seja a mais sem graça

A engenharia de software tem uma tendência a premiar a complexidade.

Um diagrama cheio de serviços, filas, bancos de dados, barramentos de eventos e componentes de infraestrutura pode impressionar.

Mas os usuários não veem nada disso.

Eles veem se o produto carrega rápido. Veem se os dados deles estão seguros. Veem se um recurso funciona quando precisam dele. Veem se o produto passa confiança.

É para dar suporte a isso que a arquitetura existe, no fim das contas.

Às vezes, isso significa microsserviços.

Às vezes, significa um monólito modular.

Às vezes, significa algo no meio do caminho.

O erro é achar que uma arquitetura mais complicada significa automaticamente um time de engenharia mais maduro.

Boa arquitetura não tem a ver com quantas tecnologias você consegue enfiar num sistema.

Tem a ver com construir algo fácil o bastante de entender, confiável o bastante de operar e flexível o bastante para mudar quando o produto mudar.

Talvez seja por isso que alguns times estão voltando para os monólitos.

Eles não estão necessariamente abrindo mão da escalabilidade.

Estão percebendo que simplicidade também é uma forma de escalabilidade — principalmente quando o que precisa escalar não é só a infraestrutura, mas o time que está construindo o produto.