ArquiteturaDesenvolvimento

Arquitetura de Monorepo Distribuída: Baseada no Livro Migrando Monolitos para Microserviços

há 2 diasPor Kaique Yamamoto

Monorepo distribuído une um único repositório à execução em serviços independentes. Este artigo conecta as ideias do livro Migrando Monolitos para Microserviços com práticas de monorepo, bounded contexts e evolução gradual.

Introdução

A arquitetura de monorepo distribuída combina duas ideias poderosas: um único repositório para todo o código (monorepo) e serviços independentes que rodam em processos separados e se comunicam por rede (microserviços). Esse modelo é especialmente útil quando você está migrando um monolito para microserviços: o livro Migrating Monoliths to Microservices (O'Reilly, em português algo como Migrando Monolitos para Microserviços) e o clássico artigo de Martin Fowler sobre Microservices oferecem a base conceitual que este artigo aplica ao uso de monorepo nessa jornada.

Assim como a padronização de conteúdo técnico segue README, TEMPLATE e CLAUDE no diretório de conteúdo do blog, a migração de um monolito exige padrões claros de organização de código, limites de contexto e deploy. Aqui você encontra um roteiro alinhado a essas fontes, com backlinks para outros artigos do blog e referências externas.

Tempo de leitura: ~18 minutos


O Que é Monorepo Distribuído?

Monorepo distribuído é a combinação de:

  1. Monorepo: todo o código (monolito legado + novos microserviços + bibliotecas compartilhadas) em um único repositório Git.
  2. Distribuído: parte ou toda a aplicação roda como serviços independentes, cada um em seu próprio processo (ou conjunto de processos), comunicando-se por HTTP, mensageria ou eventos.

O guia de Monorepo com Turbopack cobre a estrutura e o tooling de um monorepo moderno; aqui o foco é como esse mesmo repositório único suporta uma evolução gradual de monolito para microserviços, na linha do livro Migrating Monoliths to Microserviços.


Por Que Usar Monorepo na Migração para Microserviços?

No artigo Microservices, Fowler e Lewis destacam que a passagem de um monolito para microserviços envolve mudar o padrão de comunicação: de chamadas in-memory para APIs mais grossas e resilientes. Fazer essa mudança com o código espalhado em vários repositórios aumenta a complexidade de refatoração e de contratos entre times.

Com monorepo:

  • Refatorações atômicas: você pode extrair um módulo do monolito e criar um novo serviço no mesmo commit, mantendo histórico e diff claros.
  • Bibliotecas compartilhadas: tipos, contratos e utilitários vivem em packages/ e são consumidos tanto pelo monolito quanto pelos microserviços, reduzindo divergência.
  • Visibilidade: todos os serviços e o monolito estão no mesmo lugar; limites de contexto (bounded contexts) podem ser mapeados para pastas ou workspaces.
  • CI/CD único: um pipeline pode construir e testar o monolito e os serviços, com cache e builds incrementais (por exemplo com Turborepo).

Conceitos do Livro “Migrando Monolitos para Microserviços”

O livro Migrating to Microservices (e a literatura associada) enfatiza evolução gradual e redução de risco. Abaixo, conceitos que se encaixam bem em um monorepo distribuído.

Bounded Context (Contexto Delimitado)

  • Ideia: dividir o domínio em contextos com modelo e linguagem próprios; cada contexto pode virar um serviço.
  • No monorepo: cada bounded context pode ser um workspace ou pacote (apps/contexto-a, apps/contexto-b, packages/dominio-compartilhado). O monolito pode coexistir em apps/monolito enquanto você extrai módulos para apps/servico-x.

Strangler Fig (Figueira Estranguladora)

  • Ideia: não reescrever o monolito de uma vez; interpor novos serviços na frente de partes do monolito e, aos poucos, desativar trechos do monolito.
  • No monorepo: o código do monolito e dos novos serviços fica no mesmo repo; roteamento (API Gateway, proxy, ou mesmo código no monolito) redireciona tráfego para o novo serviço. Quando um trecho do monolito deixa de ser usado, você pode removê-lo em um commit atômico.

Smart Endpoints, Dumb Pipes

  • Ideia (do artigo de Fowler): a lógica fica nos serviços; a comunicação é o mais simples possível (HTTP/REST, mensageria leve), sem ESB pesado.
  • No monorepo: contratos (OpenAPI, tipos TypeScript) podem ficar em packages/contracts; cada serviço e o monolito consomem o mesmo contrato, facilitando evolução e compatibilidade.

Dados Descentralizados

  • Ideia: cada serviço tende a ter seu próprio armazenamento; consistência eventual e operações compensatórias em vez de transações distribuídas.
  • No monorepo: a escolha de banco por serviço não muda; o que melhora é a visibilidade das migrações de dados (scripts, schemas ou documentação em pastas do repo) e a coordenação entre times.

Para padrões de comunicação assíncrona e eventos entre serviços, o guia de Event-Driven Architecture com C#, .NET e Kafka complementa essa visão com mensageria e eventos.


Estrutura Sugerida do Monorepo na Migração

Uma estrutura possível, alinhada ao livro e ao uso de monorepo:

monorepo/
├── apps/
│   ├── monolito/          # Aplicação legada (a ser estrangulada)
│   ├── gateway/            # API Gateway ou BFF (opcional)
│   ├── servico-pedidos/    # Novo microserviço
│   ├── servico-catalogo/   # Novo microserviço
│   └── ...
├── packages/
│   ├── contracts/          # Contratos (OpenAPI, tipos)
│   ├── shared-types/       # Tipos compartilhados
│   └── shared-utils/       # Utilitários comuns
└── tooling/                # Configs compartilhadas (opcional)
  • apps/monolito: permanece até que todas as capacidades relevantes tenham sido movidas (strangler fig).
  • apps/servico-*: cada serviço é deployável de forma independente, mas o código vive no mesmo repo.
  • packages/contracts: reduz duplicação de definições e ajuda a manter compatibilidade entre monolito e serviços.

Riscos e Mitigações

RiscoMitigação
Monorepo muito grandeSparse checkout, builds incrementais (Turborepo), limites por bounded context
Acoplamento oculto entre serviçosContratos explícitos, testes de contrato (consumer-driven), revisão de dependências entre packages
Deploy acidental do monolito inteiroPipeline que deploya apenas apps alterados; feature flags e roteamento gradual (strangler)
Dados e consistênciaMigrações de dados planejadas, consistência eventual, operações compensatórias (livro + Fowler)

Conclusão

Uma arquitetura de monorepo distribuída, pensada para a migração de monolito para microserviços, aproveita o melhor dos dois mundos: um único repositório para refatorações atômicas, compartilhamento de código e visibilidade, e serviços independentes para deploy, escala e ownership por time. Os conceitos do livro Migrando Monolitos para Microserviços — bounded context, strangler fig, smart endpoints e dados descentralizados — se aplicam de forma prática quando o código está organizado em monorepo, como no guia de Monorepo com Turbopack, e quando a comunicação entre serviços segue padrões como os do guia de EDA com C#, .NET e Kafka.


Referências e Leitura Adicional

Tags:MonorepoMicroserviçosMonolitoMigraçãoArquitetura DistribuídaBounded Context

Artigos Relacionados

Vamos conversar sobre seu projeto?

Entre em contato para discutir como posso ajudar a transformar suas ideias em soluções tecnológicas de alta qualidade.

WhatsApp