Microsserviços Vs Monolítico: por que nem sempre a arquitetura mais complexa é a melhor?
- #Java
- #DDD
- #Microsserviços
- #Clean Architecture
Introdução
Nos últimos anos, a arquitetura de microsserviços ganhou bastante popularidade no desenvolvimento de software. É comum encontrar projetos que utilizam essa abordagem, principalmente quando falamos de sistemas escaláveis, aplicações distribuídas e grandes plataformas.
Porém, existe uma questão importante que muitas vezes acaba sendo deixada de lado: será que todo projeto realmente precisa de microsserviços?
É fácil associar uma arquitetura distribuída a um projeto mais moderno, organizado e escalável. Entretanto, essa percepção pode se tornar uma armadilha, principalmente para desenvolvedores que estão começando na área de arquitetura de software.
A verdade é que cada abordagem possui vantagens, desvantagens e cenários em que faz mais sentido ser utilizada.
Neste artigo, vamos entender como funcionam as arquiteturas monolítica e de microsserviços, suas principais características, quando utilizar cada uma e por que começar com uma arquitetura mais simples pode ser uma decisão muito mais inteligente.
1. Arquitetura Monolítica: simplicidade e centralização
Na arquitetura monolítica, a aplicação é construída como uma única unidade executável ou implantável.
Isso significa que diferentes funcionalidades do sistema, como usuários, produtos, pagamentos e pedidos, fazem parte da mesma aplicação.
Por exemplo, imagine um sistema de e-commerce. Dentro de uma aplicação monolítica, podemos ter módulos responsáveis por:
- Gerenciamento de usuários;
- Cadastro e gerenciamento de produtos;
- Carrinho de compras;
- Processamento de pedidos;
- Pagamentos.
Mesmo que essas funcionalidades estejam organizadas em pacotes, módulos ou camadas diferentes, elas pertencem à mesma aplicação e normalmente são implantadas juntas.
Principais características:
- Uma única aplicação principal;
- Geralmente um único processo de implantação;
- Comunicação interna por chamadas de métodos ou componentes;
- Menor complexidade operacional inicial;
- Facilidade para desenvolver, testar e executar localmente;
- Possibilidade de compartilhar recursos e transações dentro da aplicação.
Vantagens:
A principal vantagem está na simplicidade. É mais fácil configurar o ambiente, realizar o deploy, acompanhar logs e entender o fluxo de execução.
Além disso, chamadas entre componentes acontecem dentro da própria aplicação, sem necessariamente depender de comunicação pela rede.
Desvantagens:
Conforme o sistema cresce, a aplicação pode ficar mais difícil de manter caso não exista uma boa organização interna.
Outro problema é que uma alteração em determinado módulo pode exigir a implantação de toda a aplicação novamente.
Também existe a possibilidade de escalar recursos desnecessariamente: se apenas o processamento de pagamentos precisa de mais capacidade, talvez seja necessário aumentar os recursos da aplicação inteira.
Mas existe um detalhe importante: uma aplicação monolítica não precisa ser desorganizada. É possível utilizar princípios como Clean Architecture, DDD, separação de responsabilidades e modularização para construir um monólito muito bem estruturado.
2. Arquitetura de Microsserviços: independência e distribuição
Diferentemente do monólito, a arquitetura de microsserviços divide o sistema em serviços menores e relativamente independentes.
Cada serviço é responsável por um domínio ou conjunto específico de funcionalidades e pode possuir seu próprio ciclo de desenvolvimento, implantação e escalabilidade.
Voltando ao exemplo do e-commerce, poderíamos dividir a aplicação em:
- Product Service: gerenciamento de produtos;
- User Service: gerenciamento de usuários;
- Order Service: gerenciamento de pedidos;
- Payment Service: processamento de pagamentos;
- Inventory Service: controle de estoque.
Nesse cenário, cada serviço possui uma responsabilidade bem definida e pode ser desenvolvido e implantado de maneira independente.
A comunicação entre eles pode acontecer por meio de APIs REST, gRPC ou mensageria, utilizando tecnologias como RabbitMQ e Apache Kafka.
Principais características:
- Serviços com responsabilidades específicas;
- Implantação independente;
- Possibilidade de utilizar tecnologias diferentes quando necessário;
- Comunicação entre serviços pela rede;
- Possibilidade de escalar cada serviço individualmente;
- Maior autonomia para equipes e domínios de negócio.
Vantagens:
Uma das principais vantagens é a escalabilidade independente.
Por exemplo, se o serviço de pedidos recebe muito mais requisições do que o serviço de usuários, podemos aumentar a capacidade do primeiro sem precisar escalar toda a aplicação.
Outra vantagem é o isolamento de falhas. Problemas em um serviço não precisam necessariamente derrubar todo o sistema, desde que a arquitetura tenha mecanismos adequados de resiliência e tratamento de falhas.
Também existe maior autonomia para equipes trabalharem em diferentes partes do sistema.
Desvantagens:
É aqui que precisamos ter bastante atenção.
Microsserviços introduzem uma complexidade que não existe da mesma maneira em um monólito.
Agora precisamos lidar com:
- Comunicação entre serviços pela rede;
- Latência e possíveis falhas de comunicação;
- Consistência de dados entre diferentes serviços;
- Monitoramento e rastreamento distribuído;
- Versionamento e compatibilidade de APIs;
- Gerenciamento de infraestrutura;
- Estratégias de segurança entre serviços;
- Deploy, observabilidade e orquestração.
Ou seja, não basta dividir uma aplicação em vários projetos e chamar isso de microsserviços. É necessário pensar em toda a estrutura que permitirá que esses serviços funcionem corretamente em conjunto.
3. Quando utilizar cada arquitetura?
Não existe uma arquitetura universalmente melhor. A escolha depende do tamanho do sistema, das necessidades do negócio, da equipe e da complexidade operacional que a organização consegue administrar.
Quando um monólito pode ser a melhor escolha?
- Projetos pequenos e médios;
- MVPs e validações de ideias;
- Sistemas com regras de negócio relativamente simples;
- Equipes pequenas;
- Aplicações que não possuem necessidades específicas de escalabilidade independente;
- Projetos em que a velocidade de desenvolvimento e a simplicidade operacional são prioridades.
Quando microsserviços podem fazer mais sentido?
- Sistemas grandes e com domínios bem definidos;
- Aplicações com diferentes necessidades de escalabilidade;
- Equipes independentes trabalhando em diferentes serviços;
- Sistemas que precisam de ciclos de implantação independentes;
- Cenários em que determinados componentes precisam evoluir de maneira independente;
- Plataformas que possuem requisitos específicos de disponibilidade, isolamento e distribuição.
Um ponto importante: não é o número de funcionalidades que determina se um sistema precisa ser dividido em microsserviços. O que realmente importa é a necessidade de independência entre os domínios e os benefícios que essa divisão proporciona.
4. A armadilha de utilizar microsserviços sem necessidade
Esse é um dos pontos que considero mais interessantes nessa discussão.
Quando estamos começando a estudar arquitetura de software, é muito fácil ficar empolgado com tecnologias como Docker, Kubernetes, RabbitMQ, Kafka, API Gateway e Service Discovery.
Todas elas são importantes e possuem aplicações muito interessantes.
O problema começa quando tentamos encaixar todas essas tecnologias em qualquer projeto, mesmo quando não existe uma necessidade real.
Imagine uma aplicação simples de gerenciamento de tarefas, com poucos usuários e funcionalidades.
Será que realmente precisamos criar cinco microsserviços, configurar um API Gateway, implementar Service Discovery, utilizar mensageria e administrar múltiplos bancos de dados?
Provavelmente não.
Podemos acabar criando uma infraestrutura muito mais complexa do que o próprio problema que estamos tentando resolver.
Isso traz custos adicionais, aumenta o tempo de desenvolvimento e exige conhecimentos de infraestrutura, monitoramento e comunicação distribuída que talvez nem sejam necessários naquele momento.
E essa é uma armadilha que pode acontecer principalmente com desenvolvedores iniciantes: confundir complexidade arquitetural com qualidade de software.
Uma arquitetura não é melhor simplesmente porque utiliza mais tecnologias ou possui mais componentes.
A melhor arquitetura é aquela que resolve o problema de maneira adequada, considerando os requisitos atuais e a possibilidade de evolução do sistema.
5. Começar com um monólito e evoluir quando necessário
Existe uma abordagem que considero bastante interessante: começar com um monólito bem estruturado e, conforme o sistema cresce, avaliar se realmente existe a necessidade de extrair determinados componentes para microsserviços.
Essa ideia está relacionada ao conceito de Monólito Primeiro (Monolith First), frequentemente associado às discussões sobre arquitetura evolutiva.
A proposta não é afirmar que todo sistema deve obrigatoriamente começar como monólito, mas evitar assumir desde o início os custos de uma arquitetura distribuída sem conhecer suficientemente o domínio do negócio.
Por exemplo, imagine que começamos um e-commerce como um monólito modular.
Inicialmente, temos os módulos de produtos, usuários, pedidos e pagamentos, todos organizados e com responsabilidades bem definidas.
Com o crescimento da aplicação, percebemos que o processamento de pedidos passou a exigir muito mais recursos e possui um ciclo de evolução diferente dos demais módulos.
Nesse momento, podemos avaliar a extração do módulo de pedidos para um serviço independente.
Essa decisão passa a ter uma justificativa técnica e de negócio.
Entretanto, essa transformação exige planejamento. Precisamos considerar a separação dos dados, contratos de comunicação, consistência e possíveis dependências entre os módulos.
Um monólito bem modularizado facilita essa evolução, mas não garante que a extração será simples ou automática.
O mais importante é que a decisão seja tomada com base em necessidades reais, e não apenas em tendências tecnológicas.
6. Service Discovery e API Gateway: componentes importantes no ecossistema de microsserviços
Quando começamos a trabalhar com microsserviços, aparecem alguns componentes que ajudam a organizar a comunicação e o gerenciamento dos serviços.
Dois conceitos importantes são o Service Discovery e o API Gateway.
Service Discovery
Em uma arquitetura distribuída, os serviços podem ser executados em diferentes máquinas, containers ou instâncias.
Mas como um serviço descobre o endereço de outro serviço quando precisa realizar uma comunicação?
É justamente esse o problema que o Service Discovery ajuda a resolver.
Ele permite que os serviços sejam registrados e descobertos dinamicamente, evitando que seja necessário configurar manualmente todos os endereços de comunicação.
Podemos dividir esse conceito em duas partes:
- Service Registration: o serviço registra sua localização em um mecanismo de descoberta.
- Service Discovery: outro serviço consulta esse mecanismo para descobrir onde está o serviço desejado.
Um exemplo de tecnologia utilizada nesse contexto é o Netflix Eureka.
API Gateway
O API Gateway funciona como uma porta de entrada para as requisições externas de uma arquitetura de microsserviços.
Em vez de o cliente precisar conhecer diretamente o endereço de cada serviço, ele realiza as requisições ao Gateway, que direciona cada solicitação ao serviço responsável.
Entre suas funcionalidades, podemos encontrar:
- Roteamento de requisições;
- Autenticação e autorização;
- Rate Limiting;
- Monitoramento;
- Controle de acesso;
- Agregação de respostas, quando necessário.
Por exemplo, em um e-commerce, uma requisição para consultar produtos pode chegar ao API Gateway e ser encaminhada ao Product Service.
Já uma requisição relacionada a pedidos pode ser direcionada ao Order Service.
É importante entender que esses componentes não são obrigatórios em toda arquitetura de microsserviços. Sua utilização depende da necessidade e da complexidade do ambiente.
Também não devemos confundir suas responsabilidades: o Service Discovery ajuda a localizar serviços, enquanto o API Gateway centraliza a entrada e o roteamento das requisições externas.
Conclusão
Estudar arquitetura de software vai muito além de conhecer ferramentas e tecnologias.
É importante entender os problemas que cada abordagem procura resolver e, principalmente, reconhecer quando determinada solução pode acabar trazendo mais dificuldades do que benefícios.
Microsserviços são extremamente úteis em determinados cenários, mas também exigem maturidade arquitetural, planejamento e uma infraestrutura capaz de lidar com a complexidade de um ambiente distribuído.
Por outro lado, um monólito bem projetado pode atender muito bem às necessidades de uma aplicação, oferecendo simplicidade, organização e facilidade de manutenção.
Como desenvolvedor em formação, considero importante estudar as duas abordagens e não cair na ideia de que precisamos utilizar sempre a arquitetura mais complexa para construir um bom software.
Antes de escolher uma arquitetura, precisamos entender o problema. Afinal, não faz sentido construir uma solução muito mais complexa do que aquilo que realmente precisamos resolver.
E fica uma reflexão para a comunidade:
Vocês preferem começar um projeto com um monólito bem estruturado e evoluir conforme a necessidade, ou acreditam que determinados projetos já devem nascer utilizando microsserviços?
Gostaria de conhecer a opinião de vocês!



