Micro Serviços? Monolitos? Depois da conversa com o tipo chatgpt cheguei na ideia de Macro-Serviços

Disclaimer

Neste post não estou tentando denegrir as outras arquiteturas ou colocar Micro Serviços sobre Macro Serviços, Macro Serviços sobre Monólitos.

Ou qualquer tipo de coisa nesse sentido.

Hoje vim mostrar um pensamento aleatório de como um micro-serviço pode ser mais custoso de lidar do que um monólito e como podemos ir para um meio-termo antes de fazer migração total de arquitetura

Introdução

Todo mundo tá cansado de ouvir falar de AI, eu incluso.

Mas, jamais reclamaria da capacidade das LLM de fazer o método Investigativo com um modelo descente aka DeepSeek, aka Copilot, Llama e ChatGPT.


Por quê? Às vezes a forma que a LLM responde me dá vontade de explicitar coisas que eu não coloquei em contexto e de certa forma tentar ver mais do que consigo enxergar.

Então eu me questionei.

Por que Micro Serviços?

Porque precisamos isolar parte da lógica para atender diversas partes do código, permitindo que cada uma evolua de forma independente.

Isso ajuda a aumentar a performance em escala, possibilita a escalabilidade seletiva de serviços específicos (por exemplo, escalar apenas o serviço de pagamentos em datas comemorativas), melhora a resiliência a falhas (se um serviço falhar, os demais continuam funcionando) e facilita a manutenção ao permitir que equipes distintas trabalhem em diferentes serviços de maneira mais autônoma e coesa.

Porque Monólitos?

Porque é a mais fácil de manter (única codebase), mais simples de deployar, e mais fácil de testar de forma E2E.

No entanto, essa simplicidade cobra seu preço: é difícil escalar seletivamente — se apenas o módulo de checkout precisa de mais recursos, você ainda precisa escalar toda a aplicação — e mudanças em larga escala podem gerar efeitos colaterais imprevisíveis em módulos não relacionados.

A interdependência interna também torna mais desafiadora a adoção de múltiplas tecnologias ou a divisão de trabalho entre equipes especializadas. Tudo é escalado em conjunto.


Claro que aqui eu fiz um resumo muito absurdo que provavelmente foi parcial, sorry.

Mas o ponto que eu chego é que micro-serviços crescem e se expandem como uma praga já que uma vez que você começa a dividir um monólito você não sabe onde parar já que tudo começa a ter uma cara de serviço.

E tudo bem, mas 10 micro-serviços de User, Payments, Database, Replication, etc., começam a gerar mais ruído do que valor.

Essa fragmentação exagerada acarreta uma sobrecarga operacional significativa:

  • múltiplos repositórios
  • múltiplas pipelines de CI/CD
  • múltiplas deployagens independentes
  • múltiplos pontos de falha

Além disso, há uma sobrecarga cognitiva real — entender a arquitetura, fazer debugging entre serviços e garantir coesão funcional se torna um verdadeiro pesadelo, especialmente para times pequenos ou menos experientes.

Tanto para manter quando para entender para que tudo isso serve.

E nisso eu pensei porque não um Macro-Serviço

Contexualizando Macro-Serviço

É um micro-serviço grande apenas isso.

Mas aplicado ao famoso DDD (Domain-Driven Design), uma abordagem de design de software que foca em modelar a lógica de negócio com base em domínios reais, aproximando código e linguagem do problema do mundo real.

O DDD propõe organizar o sistema em torno de "bounded contexts" — contextos delimitados — que representam áreas específicas do negócio, promovendo maior coesão interna e clareza arquitetural.

Em vez de você pensar no micro-serviço, você começa a pensar no contexto do domínio em que o serviço vai ser utilizado.

Exemplo (grande nível): Netflix

E obviamente, vamos usar a Netflix de exemplo. Afinal todo grande exemplo tem que começar de algo insustentável.

Se fossemos construir uma Netflix do zero usando micro-serviços teriamos algo como:

Micro Serviço Utilidade
video-catalog-service Lista de vídeos e metadados
recommendation-service Sistema de recomendação
transcoding-service Conversão de vídeo
user-profile-service Dados do usuário
auth-service Login e sessão
watch-history-service Histórico de visualizações
billing-service Pagamentos e planos
subtitle-service Legendas
drm-service Proteção de conteúdo

Mas se fossemos construir uma Netflix do zero usando macro-serviços teriamos algo como:

Macro Serviço Utilidade
ContentDomain Catálogo, metadados, transcodificação, legendas, DRM
UserDomain Perfil, histórico, login
RecommendationDomain Personalização, ranking, machine learning
BillingDomain Cobrança, assinatura, controle de acesso
PlaybackDomain Entrega de vídeo, qualidade adaptativa, telemetria

Exemplo (nível menor): Lojinha do seu Zé

Se fossemos aplicar Micro-Serviços a lojinha do seu zé. Provavelmente teriamos algo como:

Micro Serviço Utilidade
auth-service login
user-service clientes
product-service produtos
stock-service estoque
order-service pedidos
payment-service integração com Pix
report-service relatórios
notification-service e-mails (que o Zé nem usa)

Ok, isso ficou arquiteturalmente mais complexo do que deveria. Então usando Macro-Serviços teriamos

Macro Serviço Utilidade
customer-domain login, cadastro, dados do cliente
sales-domain pedidos, produtos, estoque
finance-domain pagamento via Pix e relatórios de venda

Analise profunda

Veja que a ideia continua sendo a mesma, um serviço remoto sendo chamado por protocolo de rede a outra instância, preferencialmente em outra máquina. Essas comunicações geralmente utilizam tecnologias como REST, gRPC ou filas de mensagens (message queues), dependendo das necessidades de latência, complexidade e escalabilidade do sistema.

Mas temos algumas diferenças de contexto aqui.

O Micro Serviço tende fazer pequenas coisas por contexto, enquanto um Macro-Serviço quer controlar um dominio inteiro por contexto.

Isso tem vantagens e desvantagens e cada a analise profunda do sistema.

Critério Monolito Microserviço Macroserviço
Complexidade Inicial Baixa: uma única codebase, simples de entender Alta: múltiplos repositórios, múltiplos deploys Média: divisão por domínio, mas ainda modular
Escalabilidade Escala tudo ou nada Escala apenas o necessário, independentemente Escala por domínio (parcialmente granulado)
Deploy e CI/CD Único pipeline Vários pipelines independentes Pipelines por domínio (menos que micro, mais que mono)
Desempenho Interno Alto, sem chamadas de rede Overhead por chamadas de rede e comunicação interserviços Overhead moderado, menos granular
Isolamento de Falhas Falha pode afetar todo o sistema Falhas isoladas por serviço Isolamento por domínio
Gerenciamento de Equipes Difícil dividir equipe por responsabilidade Times independentes por serviço Times por domínio funcional
Custo Operacional Baixo para pequeno/médio porte Alto: precisa de orquestração, observabilidade, monitoramento Médio: menos serviços para orquestrar
Manutenibilidade Simples até crescer demais Alto custo cognitivo Melhor legibilidade e contexto
Flexibilidade Tecnológica Limitada a stack única Pode variar stack por serviço Stack por domínio, com controle melhor definido
Curva de Aprendizado Rasa Íngreme Média
Velocidade de Desenvolvimento Alta no início, cai com escala Lenta no início, mais sustentável depois Boa tração no início e manutenção decente ao escalar

Conclusão

Esse aqui é o resultado do pensamento de um dia, feito graças a um vídeo do Augusto Galego (link abaixo). E que precisa ser estudado mais a fundo.

Minha recomendação pessoal é não ir direto a Macro ou Micro Serviços.

Comece com monolitos e veja se a mudança arquitetural é justificada ou não, ademais espero que tenham curtido esse post valeu.

Sempre que tiver uma conversa com uma IA potencialmente estará prestes a tomar uma das piores decisões. Infelizmente algumas pessoas já não conseguem ter essa ideia e aceitam como verdade que a IA sabe alguma coisa corretamente. Ela é só baseada em estatísticas com uma dose de aleatoriedade para não parecer mecânico demais e por isso ela só falará o que é mais falado na internet, ou seja, se o erro for muito falso é ele que você obterá. A IA não achará nada que não está presente na internet ou que esteja relativamente "escondido". Por isso é um método investigativo falho. Não quer dizer que ela não dará algum resultado e pode prestar para alguma coisa, mas o fato de poder ser falho e as pessoas acreditarem que não é um enorme problema.

Claro, muitos humanos fariam pior, mas ainda não é desculpa. Obviamente que ela serve de ajuda, mas poucas pessoas sabem como usar de forma adequada, inclusive eu não sei, mesmo tendo esse pensamento bastante questionador.

A definição sobre microsserviços está errada, começando pelo título. Não é necessário microsserviços para alcançar nada daquilo e ele pode não alcançar qualquer uma dessas coisas se feito errado, embora ainda seja microsserviços.

Também não é verdade o que se fala sobre monólitos, sabendo fazer ele escala do jeito que precisa e temos diversas provas disso. Não conheço e já procurei bastante, parece não haver nenhuma prova que qualquer aplicação precisa de microsserviços para escalar, embora alguma pode ser um pouco mais fácil (pagando o preço geral para ter algo tão complexo, também precisaria de uma prova que os problemas compensam os benefícios).

As pessoas confundem arquitetura monolítica com executável monolítico, o que em algumas tecnologias nem faz sentido.

Da mesma forma que podemos separar funções em um monólito, podemos escalar só as que queremos.

Está correto os problemas sobre microsserviços, ainda que não seja completo.

Microsserviços nunca foi sobre tamanho, então ele ser pequeno ou grande não muda nada.

DDD pode ajudar ou atrapalhar a execução de uma aplicação, já vi muitos casos de terror adotando essa técnica e a verdade é que se feito como manda o manualzinho praticamente já temos microsserviços, ainda que funcione de forma mais monolítica. Inclusive um dos problemas é que as pessoas não sabem onde achar a borda do contexto, especialmente quando eles se interseccionam.

A tabela sobre microsserviços da Netflix são megaserviços. Ok, pode ser só para ilustrar que deveriam ter menos. Mas aí é que está não é assim que se define contextos, não se pode olhar para o tamanho.

A tentativa de fazer menos serviços conseguirá o pior dos dois mundos.

Tudo isso mostra que o foco está sendo em usar uma tecnologia complexa sem se preocupar com o valor que isso apresenta, algo que quase todo mundo faz quando pensa em microsserviços. Em vez de fazer o simples até que se prove que tem um motivo para fazer diferente.

Quando se faz isso quase sempre, para não dizer sempre, até porque até os grandes que usam microsserviços provavelmente não precisam disso, e alguns dão mostram que estão pagando um preço alto pela escolha errada há 10 anos, outros até estão voltando atrás, o monólito é muito melhor por diversas razões.

Mas é claro que algum ponto pode se tornar uma dificuldade e aí nesse ponto específico pode-se fazer um serviço separado. Note que não importa o tamanho dele, e a arquitetura não é de microsserviços, apenas que esse ponto você precisa de algo completamente desacoplado como se fosse uma outra empresa sem comunicação fácil com o resto trabalhando nisso, assim podem fazer o deploy do jeito que quiserem, usar a tecnologia que acharem mais adequada, escalar de forma diferente ou fpenas fazer bico para os demais que mexer no sistema.

A IA só consolidará mais o erro, validará quem precisa disso mesmo quando for algo errado, só dará argumentos falhos para quem não entende oque está fazendo e criar seu próprio conhecimento, o que tornará a vida difícil para quem entende. Vamos viver épocas bem complicadas.

Microsserviços já é aceito por cada vez mais pessoas, até os primeiros proponentes, embora esteja longe de aceitação total, como algo apenas para se adequar à lei de Conway quando a empresa já é micro equipes com independência total.

Outra coisa que passa batido é que só faz sentido em equipes de pelo menos centenas de pessoas, o que é bem raro.

E essa coisa de meio termo pode ser o pior de tão artificial que é.

A tabela tem informações inventadas, algumas eu já falei como a ideia que monólito só escala tudo. Não é algo matemático que você só faz a média e tá tudo certo.

A curva de aprendizado do tal do "macro" é essencialmente igual ao do micro, e mesmo monólito bem feito, se for muito grande também não é tão fácil assim, ele é mais fácil de manter. Em ado momento ter 10 ou 100 dá quase na mesma, até mesmo pode ser 2. Ter 1 é diferente, tem seus custos e benefícios.

Monólito não precisa falhar tudo, tem diversas técnicas, algumas até mais simples para resolver isso. Essas visões são de pessoas que não entendem a computação, que aprenderam com blogs e vídeos de Youtube. Uma das coisas que eu mais vejo acontecer é microsserviços falhar, porque existem duas formas de fazer isso, uma delas faz haver falhas em cascata e a outra é de extrema ineficiência, na prática você não tem microsserviços, você tem um monte de "pequenas" aplicações completas.

Só é difícil dividir equipe por responsabilidade por incompetência gerencial, o que vai dar na mesma ou pior quando separa de forma mais forte, inclusive porque passa ter que lidar com egos mais inflados pela independência que receberam. De qualquer forma cada caso é um caso. Pode ser sim ser a melhor solução, mas depende do caso concreto.

Não é verdade que monólito só pode usar uma stack, embora tenha limitações no que pode flexibilizar, e novamente, se uma parte precisa de algo diferente, dá para fazer só isso. Separar para todo mundo usar coisas diferentes não resolve problema real algum, pelo contrário, traz problema novo.

Não há nenhuma informação que indique que microsserviços são mais rápidos de dar manutenção. Minha observação é a oposta. Ele começa criar uma quantidade monstruosa de dívida técnica.

E o pior, para saber de tudo isso precisa de uma experiência que ninguém tem.

Ah, existe uma diferença entre fazer uma arquitetura de microsserviços e ter várias aplicações. Nunca fez sentido ter uma única aplicação dentro de uma empresa.

Eu tenho experiência com monólitos rodando em milhares de empresas em ambientes enormes e não é como alguns vendem, funciona muito bem e não a tragédia que manter e escalar como dizem, inclusive quando tem muita gente ruim na equipe. Eu nunca vi um sistema em microsserviços funcionando maravilhosamente como alguns dizem. Eu jamais vou trocar o certo pelo incerto, isso não é engenharia.

O final é o que tem de melhor no texto, pena que muitos vão achar uma justificativa falsa para dividir o que não precisa, já vi uma quantidade inacreditável assim.

Uma das maiores justificativas que eu recebo para as pessoas irem para microsserviços, que é computação distribuída, considerada por muitos o problema mais difícil de se resolver, é que elas não possuem bons profissionais, como o pessoal do Instagram, Shopify, Wikipedia e Stack Overflow tem. Ora, se não tem gente boa para fazer monólito, para microsserviço é pior ainda, só que mesmo que fique uma porcaria, vai aos trancos e barrancos, vai botando hardware, vai aumentando a equipe como um todo. Isso não é só incompetência é mau-caratismo.

Uma das coisas que eu, exagerando, falo quase como um axioma, é que quem adota microsserviços é sempre aquela que não entende ele. Ou seja, desastre à frente.

Eu acho que estou aprendendo alguns cenários que microsserviços parciais podem ser realmente muito úteis e pode trazer mais vantagem que prejuízo, mas não é da forma que a maioria usa. Um dia talvez eu formalize, quem sabe execute e coloque em público.

S2


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui no perfil também).

> Sempre que tiver uma conversa com uma IA potencialmente estará prestes a tomar uma das piores decisões. Infelizmente algumas pessoas já não conseguem ter essa ideia e aceitam como verdade que a IA sabe alguma coisa corretamente. Ela é só baseada em estatísticas com uma dose de aleatoriedade para não parecer mecânico demais e por isso ela só falará o que é mais falado na internet, ou seja, se o erro for muito falso é ele que você obterá. A IA não achará nada que não está presente na internet ou que esteja relativamente "escondido". Por isso é um método investigativo falho. Não quer dizer que ela não dará algum resultado e pode prestar para alguma coisa, mas o fato de poder ser falho e as pessoas acreditarem que não é um enorme problema. Concordo totalmente, acredito que método investigativo foi um termo até que bem falho, no caso deveria ser [método socrático](https://pt.wikipedia.org/wiki/M%C3%A9todo_socr%C3%A1tico) onde na teoria eu preciso que a LLM me retorna alguma coisa (qualquer coisa) baseada no tema de entrada para dar continuidade a linha de pensamento. > A tabela tem informações inventadas, algumas eu já falei como a ideia que monólito só escala tudo. Não é algo matemático que você só faz a média e tá tudo certo. No caso, as tabelas também seriam uma exemplificação. Mas, a ideia de o monólito escalar tudo é que a partir do momento em que o software não pode ser mais otimizado, talvez onde a arquitetura não ajude e você comece a ter que reparticionar a aplicação em serviços menores (indo para um monólito modular). Em vez de adotar um serviço pequeno como um lambda ou coisa assim. Já separar um domínio para outro cluster de forma que tudo relacionado a esse domínio tenha latência menor do que fazendo várias requisições entre servidor principal e outros micro-serviços. Como se, por exemplo, o servidor não tenha que dar get em `UserService` para ir para `Payments` para ir para finalizar a lista de comprar no servidor principal e simplesmente ter uma troca entre `User` e o Servidor principal já que o domínio de compras está relacionado ao usuário. > Também não é verdade o que se fala sobre monólitos, sabendo fazer ele escala do jeito que precisa e temos diversas provas disso. Não conheço e já procurei bastante, parece não haver nenhuma prova que qualquer aplicação precisa de microsserviços para escalar, embora alguma pode ser um pouco mais fácil (pagando o preço geral para ter algo tão complexo, também precisaria de uma prova que os problemas compensam os benefícios). Agora essa aqui vai depender do nível da aplicação. Vou pegar o caso mais antigo e mais absurdo que tivemos, o **Twitter**. Não vai se repetir, mas é bom para exemplificar. Eles começaram com o Ruby on Rails que tinha prototipação rápida e tava indo tudo bem, até que surgiu a necessidade de recomendar coisas, e o Ruby não tinha a escala massiva para isso. A única opção na época era migrar para Scala com o framework Akka que já tinha a arquitetura pronta para lidar com processamento paralelo massivo. Mas, obviamente, eles não iriam reconstruir todo o sistema deles em escala, então inventaram o **Thrift** para comunicação em protocolo binário entre subsistemas. É um caso massivo e certamente não replicável, mas foi esse um dos pontos que o formato monólito não deu conta "a mudança de contexto em produção". > A tentativa de fazer menos serviços conseguirá o pior dos dois mundos. Nesse caso, vai depender do estudo do caso e/ou da implementação. A principal fraqueza dos micro-serviços é que são super-dependentes da rede para fazer seu processamento. O monólito escapa disso mantendo tudo em um único contexto. Dependendo da implementação, o macro-serviço teria contexto o suficiente para fazer seu processamento mesmo se a rede cair, apesar de ainda ser dependente de rede para retornar o resultado. E de alguma forma também teria menor latência em comparação com micro-serviços, já que não depende de outras chamadas para uma resposta em determinado contexto. > Só é difícil dividir equipe por responsabilidade por incompetência gerencial, o que vai dar na mesma ou pior quando separa de forma mais forte, inclusive porque passa ter que lidar com egos mais inflados pela independência que receberam. De qualquer forma cada caso é um caso. Pode ser sim ser a melhor solução, mas depende do caso concreto. Talvez, mas ainda sim ao nível de governança pode até ter um sentido mais interessante já que o servidor central onde as coisas mais importantes ficam fica por conta da mão de obra "permitida" a acessar. Enquanto outras pessoas trabalham em Macro-Serviços separados. Com o nível de encapsulamento correto. --- Independentemente, essa é uma ideia de arquitetura que somente com experiência e estudo possa ser usada ou não. Não é exatamente nosso trabalho julgar qual a melhor ou qual a pior ferramenta em caso global, apenas fazer as escolhas mais sensatas com base no contexto, experiência e conhecimento que temos.
> Mas, a ideia de o monólito escalar tudo é que a partir do momento em que o software não pode ser mais otimizado, talvez onde a arquitetura não ajude e você comece a ter que particionar a aplicação em serviços menores (indo para um monólito modular). Isso é crença, tá cheio de sistemas que escalam muito (entre os mais usados do mundo) e não precisam particionar nada. O Twitter não tinha aquela como única opção, eles usaram aquela e divulgaram, tinham diversas outras, até continuar com o que tinham com alguma alteração. De qualquer forma o que eles mudaram nada tem a ver com o que está sendo falado aqui. Isso é uma divagação que não contribui já falei mais do que deveria sobre isso. A Wikipedia é feito com um PHP porco sem arquitetura pensada, é monólito e está entre os sites mais acessados do mundo, e escala. Toda essa conversa sobre o meio termo eu já falei antes, mas parece que foi ignorado, não posso fazer nada além disso. Reforço a frase que terá o pior dos dois mundos, não é uma média matemática. A falta de conhecimento é o que leva as pessoas a tomar decisões erradas.
> Isso é crença, tá cheio de sistemas que escalam muito (entre os mais usados do mundo) e não precisam particionar nada. Concordo. Qualquer sistema baseado em leitura majoritariamente estática como a própria Wikipedia tende a escalar com facilidade, principalmente quando há camadas pesadas de cache e uso intensivo de HTML pré-renderizado. Mas usar isso como contraexemplo ao caso do Twitter é ignorar completamente o tipo de carga que eles passaram a enfrentar. A reestruturação da plataforma não foi uma decisão por hype ou modinha, foi uma imposição técnica brutal, causada pela transição de timeline sequencial para um sistema de recomendação em tempo real com milhões de conexões simultâneas. Ruby não estava nem perto de dar conta disso, nem com mágica. Citando a ti, vale a pena entender um pouco mais: - http://snap.stanford.edu/mlg2013/submissions/mlg2013_submission_20.pdf - http://www.vldb.org/pvldb/vol7/p1379-lin.pdf - https://www.vldb.org/pvldb/vol9/p1281-sharma.pdf > Toda essa conversa sobre o meio termo eu já falei antes, mas parece que foi ignorado, não posso fazer nada além disso. Reforço a frase que terá o pior dos dois mundos, não é uma média matemática. Nada é média matemática, o que tentei passar foi e repito `Se e somente se o estudo de caso apontar a necessidade clara de desacoplamento, e as abordagens mais simples forem insuficientes, aí sim faz sentido particionar — mas não em microserviços prematuros.`. > A falta de conhecimento é o que leva as pessoas a tomar decisões erradas. Erro não é falta de conhecimento, é o processo de obtê-lo. Quem nunca iterou errado, nunca operou fora da zona de conforto --- No limiar dos ânimos não estou aqui para competir experiência contigo, só mostrar que ao invés de tentar fazer isso dessa forma, pode - se tentar dessa outra em uma POC, se der certo adota, se não volte ao convencional. No mínimo vai agregar para positivo ou negativo só o tempo dirá
Eu usei a WP pra mostrar que uma linguagem lenta só é um problema por gerar mais gastos, não porque não escala, a linguagem nunca impede nada de escalar, isso é crença. Se vai refazer toda a arquitetura até faz sentido usar uma tecnologia melhor, e não precisaria ser Scala, na verdade acho que já se arrependeram de ter escolhido ela, apesar de não ter sido um norme problema. https://www.reddit.com/r/facepalm/comments/yvhjzj/elon_musk_turned_off_microservices_on_twitter/ O Instagram deve ser a mesma coisa, né? Eles não precisaram reescrever nada, continuaram com o monólito em Java, Python e JS.