Monorepo: o que é, vantagens, desvantagens e quando usar

Monorepo: o que é, vantagens, desvantagens e quando usar

Toda equipe de software chega num ponto em que precisa decidir como organizar o código. Um repositório por serviço? Um repositório gigante com tudo dentro? A pergunta parece burocrática, mas ela define como a gente compartilha código, roda CI, versiona bibliotecas e até como novos devs entram no projeto. E poucas decisões de arquitetura geram tanta discussão de corredor quanto essa.

O monorepo virou moda porque Google, Meta e Microsoft contam que rodam praticamente tudo dentro de um só repositório. Só que copiar a estratégia de quem tem centenas de engenheiros de plataforma nem sempre faz sentido pro seu time de oito pessoas. Neste post a gente vai direto ao ponto: o que é monorepo de verdade, onde ele brilha, onde ele te dá dor de cabeça, quais ferramentas resolvem os problemas reais e como saber se é hora de adotar ou fugir dele.

O que é monorepo?

Monorepo é uma estratégia de organização de código em que vários projetos, serviços ou bibliotecas ficam versionados dentro de um único repositório de controle de versão, geralmente Git. Em vez de ter dez repositórios separados (um pro frontend, um pro backend, um pra cada biblioteca compartilhada), você tem um repositório só que contém todos eles, cada um na sua pasta, compartilhando o mesmo histórico e a mesma raiz.

Uma confusão comum: monorepo não é a mesma coisa que “monólito”. Monólito é sobre arquitetura de deploy (uma aplicação única que sobe inteira). Monorepo é sobre onde o código mora. Dá pra ter um monorepo cheio de microsserviços que rodam de forma totalmente independente, e dá pra ter um monólito espalhado em vários repositórios. São eixos diferentes. Misturar os dois conceitos é a fonte de metade dos mal-entendidos sobre o tema.

Monorepo: o que é, vantagens, desvantagens e quando usar ilustracao 1

Na prática, um monorepo típico de um time web tem essa cara:

meu-produto/
├── apps/
│   ├── web/            # frontend em React
│   ├── admin/          # painel administrativo
│   └── api/            # backend Node
├── packages/
│   ├── ui/             # design system compartilhado
│   ├── config/         # ESLint, tsconfig, prettier
│   └── utils/          # funções comuns
├── package.json        # workspaces raiz
├── turbo.json          # config do build system
└── pnpm-workspace.yaml

A pasta apps guarda as coisas que rodam (os deployables), e a pasta packages guarda o que é compartilhado entre elas. O web importa o ui como se fosse uma dependência normal, mas o código está ali do lado, sem publicar nada no npm. Essa é a mágica que faz gente se apaixonar por monorepo: você muda um botão no design system e todas as apps já enxergam a mudança na hora.

Monorepo vs polyrepo: qual a diferença real

Polyrepo (ou multirepo) é o modelo tradicional: cada projeto tem seu próprio repositório, seu próprio CI, seu próprio versionamento. É o que a maioria dos times faz por padrão, muitas vezes sem nem pensar que é uma escolha. Você cria um repo pro serviço de pagamentos, outro pro serviço de usuários, e cada um segue a vida.

A diferença central não é técnica, é de fronteira. No polyrepo as fronteiras entre projetos são físicas e rígidas: pra compartilhar código você publica um pacote e a outra equipe atualiza a versão quando quiser. No monorepo as fronteiras são lógicas e porosas: o código compartilhado está a um import de distância, e uma mudança pode atravessar vários projetos num único commit.

Isso muda tudo. No polyrepo, atualizar uma biblioteca compartilhada em vinte serviços é um trabalho de formiguinha: publica versão nova, abre vinte PRs, torce pra ninguém esquecer. No monorepo, é um commit só que altera a lib e os vinte consumidores de uma vez, com o CI validando tudo junto. Em compensação, no polyrepo cada time é dono absoluto do seu espaço, sem ninguém pisando no seu callo, enquanto no monorepo você precisa de disciplina e ferramentas pra evitar que vire uma bagunça acoplada.

Aspecto Monorepo Polyrepo
Compartilhar código Import direto, sem publicar Publicar pacote e versionar
Mudança cross-projeto Um commit atômico Vários PRs coordenados
Isolamento entre times Depende de disciplina e tooling Forte por natureza
Onboarding Um clone e você tem tudo Achar e clonar N repos
CI/CD Precisa de build afetado, senão fica lento Simples, cada repo o seu
Versionamento Um histórico, versão única do código Cada projeto sua versão
Tamanho do repo Cresce rápido, pode pesar no Git Cada repo fica enxuto

Não existe vencedor absoluto nessa tabela. O que existe é encaixe com o seu contexto. Um time pequeno tocando um produto integrado tende a sofrer menos com monorepo. Vinte times autônomos, com stacks diferentes e ciclos de release independentes, muitas vezes vivem melhor no polyrepo.

Vantagens do monorepo que aparecem na prática

Compartilhamento de código sem burocracia

Essa é a vantagem que todo mundo cita primeiro, e com razão. Quando o código compartilhado mora no mesmo repo, você para de brigar com o inferno do versionamento de pacotes internos. Nada de publicar uma @empresa/utils@1.4.2, esperar o registry propagar, atualizar em cada projeto e descobrir depois que dois serviços estão em versões incompatíveis. Você importa, muda, e pronto.

Mudanças atômicas de verdade

Já precisei renomear uma função que era usada em três serviços e uma biblioteca. No polyrepo isso seria uma dança de PRs encadeados durante dias. No monorepo foi um commit: mudei a função, atualizei os quatro lugares que a chamavam, e o CI rodou tudo junto pra confirmar que nada quebrou. Essa capacidade de fazer refatorações que atravessam fronteiras de projeto num único passo atômico é, na minha opinião, o benefício mais subestimado do modelo.

Visibilidade e padronização

Com tudo no mesmo lugar, fica trivial impor um único ESLint, um único Prettier, uma única versão de TypeScript. Novos devs clonam um repositório e têm o ecossistema inteiro na frente deles, o que ajuda demais no onboarding. Buscar onde uma função é usada em toda a organização é um grep ou um “find references” no editor, não uma caçada em vinte repositórios que você nem sabe que existem.

Monorepo: o que é, vantagens, desvantagens e quando usar ilustracao 2

Reaproveitamento que acontece de fato

Tem um efeito psicológico aqui que é real. Quando compartilhar código é fácil, as pessoas compartilham. Quando exige publicar pacote e coordenar release, elas dão um jeito, copiam e colam, e você acaba com cinco versões da mesma função de formatação de data espalhadas pela empresa. O monorepo remove o atrito e, com isso, o reaproveitamento deixa de ser um discurso bonito e vira hábito.

Desvantagens honestas: o que ninguém te conta antes

CI/CD fica caro e lento se você não cuidar

Esse é o primeiro tropeço de quase todo time que adota monorepo sem preparo. Se cada push dispara o build e os testes de tudo, o pipeline vira uma tartaruga e você queima minutos de CI a rodo. A solução existe (rodar só o que foi afetado pela mudança), mas isso não vem de graça: exige um build system que entenda o grafo de dependências do repositório. Sem essa peça, o monorepo escala mal e o time começa a odiar o CI.

O Git pode sofrer com a escala

Um repositório que junta dezenas de projetos, com anos de histórico e muitos arquivos, deixa operações do Git lentas. git status, git clone e checkout começam a arrastar. Os gigantes resolveram isso com filesystems virtuais e checkout parcial (sparse checkout), mas de novo, é infraestrutura extra que o seu time vai precisar bancar. Para a maioria dos projetos de porte normal, isso não é problema, mas é bom saber que o teto existe.

Acoplamento acidental

A porosidade que é uma vantagem também é uma armadilha. Como importar de qualquer lugar é fácil, sem regras de fronteira o código vira um novelo em que tudo depende de tudo. Aí você tenta extrair um serviço e descobre que ele está amarrado em dez lugares que nunca deveriam se conhecer. Manter fronteiras saudáveis num monorepo exige regras explícitas (quem pode importar de quem) e ferramentas que reforcem isso, senão a bagunça é questão de tempo.

Permissões e propriedade ficam grosseiras

No Git, controle de acesso é por repositório. Num monorepo, se você quer que o time A não mexa no código do time B, o Git puro não resolve bem: todo mundo tem acesso a tudo. Dá pra contornar com CODEOWNERS e revisão obrigatória, mas é uma camada de processo que no polyrepo você ganha de graça só por separar os repos.

Ferramentas do ecossistema de monorepo

A boa notícia é que praticamente todas as desvantagens acima têm ferramenta pra amenizar. O que era território exclusivo do Google hoje está acessível pra qualquer time. Vale conhecer os principais nomes antes de decidir.

Turborepo

O Turborepo (mantido pela Vercel) é o queridinho do mundo JavaScript e TypeScript hoje. Ele é um build system que roda em cima dos workspaces do npm, pnpm ou yarn, e a graça dele é o cache: ele guarda o resultado de cada tarefa (build, teste, lint) e, se nada mudou naquele pacote, ele reusa o resultado em vez de rodar de novo. Esse cache pode ser remoto, compartilhado entre a máquina dos devs e o CI, o que corta tempo de pipeline de forma absurda. É simples de adotar, tem configuração enxuta e é o que eu recomendaria pra quem está começando num stack JS.

Nx

O Nx é mais poderoso e mais opinativo que o Turborepo. Além do cache e da execução de tarefas afetadas, ele traz geradores de código, um grafo de dependências visual, plugins pra vários frameworks e o conceito de fronteiras de módulo que você configura pra impedir imports proibidos. É a escolha pra times maiores que querem estrutura forte e estão dispostos a engolir uma curva de aprendizado maior. Onde o Turborepo é minimalista, o Nx quer ser a plataforma inteira.

Bazel

O Bazel é o peso-pesado, nascido do sistema interno do Google. Ele é agnóstico de linguagem (Go, Java, Python, C++, o que você quiser), tem builds herméticos e reproduzíveis, e escala pra bases de código gigantescas com milhares de alvos. O preço é a complexidade: configurar Bazel é um projeto por si só, e a experiência de desenvolvimento é bem menos amigável. Faz sentido quando você tem várias linguagens no mesmo repo e uma escala que justifica o investimento. Para um monorepo só de JS, é canhão pra matar mosquito.

Menções rápidas

Fora esses três, você vai esbarrar em outros nomes conforme a stack. O Pants e o Buck2 (esse do Meta) jogam na mesma liga do Bazel para projetos poliglotas. No mundo JS, os próprios workspaces do pnpm já resolvem o compartilhamento de dependências sem nenhuma ferramenta extra, e muita gente começa só com isso antes de adicionar um build system por cima. Não precisa de artilharia pesada no dia um.

Quando usar monorepo (e quando não usar)

Depois de tudo isso, a pergunta que importa: faz sentido pro seu caso? Vou ser direto com o que costumo recomendar.

Monorepo tende a valer a pena quando os projetos compartilham muito código e evoluem juntos. Um produto com frontend, backend e um design system que anda no mesmo ritmo é o caso clássico: as mudanças frequentemente atravessam as camadas, e um commit atômico poupa muita coordenação. Também vale quando o time é integrado o suficiente pra topar um padrão único de tooling, e quando você quer que reaproveitar código seja o caminho de menor resistência.

Vale também quando o onboarding e a visibilidade importam bastante. Se você quer que qualquer dev consiga rodar o sistema inteiro localmente com um comando, e enxergar como as peças se encaixam sem virar arqueólogo de repositórios, o monorepo entrega isso naturalmente.

Agora, quando eu evitaria. Se seus projetos são realmente independentes, com stacks distintas, sem quase nada de código compartilhado e ciclos de release que não conversam, o monorepo só adiciona atrito. Times muito autônomos, que querem ser donos totais do seu espaço sem depender de convenções coletivas, geralmente são mais felizes no polyrepo. E se você não tem apetite pra investir no tooling de build afetado e cache, um monorepo grande vai te punir com CI lento até você desistir.

Um bom teste mental: pergunte com que frequência uma mudança precisaria atravessar as fronteiras dos seus projetos. Se a resposta for “toda hora”, o monorepo está pedindo pra existir. Se for “quase nunca”, provavelmente você está inventando um problema que não tem. Comece pequeno, com os workspaces nativos do seu gerenciador de pacotes, e só adicione Turborepo ou Nx quando o CI começar a doer. Adotar Bazel no dia um porque o Google usa é a receita mais comum pra arrependimento.

Perguntas frequentes sobre monorepo

Monorepo é o mesmo que monólito?

Não. Monólito é uma decisão de arquitetura de aplicação (tudo roda como um único processo que sobe junto). Monorepo é uma decisão de organização de código (tudo mora no mesmo repositório). Você pode ter um monorepo cheio de microsserviços independentes, e pode ter um monólito cujo código está fragmentado em vários repositórios. Os dois eixos são separados e não se implicam.

Grandes empresas realmente usam monorepo?

Sim. Google, Meta, Microsoft, Uber e Airbnb são exemplos conhecidos de bases de código gigantes rodando em monorepo, algumas com bilhões de linhas. Só que eles bancam times inteiros de engenharia de plataforma pra construir os filesystems virtuais, os build systems e a infra que faz isso escalar. Copiar a estratégia sem copiar o investimento é onde muitos times pequenos se dão mal.

Qual a melhor ferramenta de monorepo para JavaScript?

Para a maioria dos times de JS ou TypeScript, o Turborepo é o ponto de partida mais tranquilo: pouca configuração, cache local e remoto, e integra direto com os workspaces do pnpm ou npm. Se você precisa de mais estrutura, geradores de código e reforço de fronteiras de módulo, o Nx é a próxima parada. Bazel só se você tiver várias linguagens e escala pra justificar a complexidade.

Monorepo deixa o Git lento?

Pode deixar, mas só em escala grande. Um monorepo com dezenas de milhares de arquivos e histórico longo torna operações como git status e clone mais lentas. As saídas são sparse checkout, shallow clone e filesystems virtuais. Para um monorepo de porte normal, com um punhado de apps e pacotes, o Git aguenta numa boa e você não vai sentir diferença no dia a dia.

Como versionar pacotes dentro de um monorepo?

Existem duas escolas. A de versão única (o repositório inteiro compartilha uma versão só, estilo Google) e a de versões independentes por pacote, que é o mais comum quando você publica bibliotecas no npm. Para o segundo caso, ferramentas como Changesets ou o Lerna automatizam o bump de versão, o changelog e a publicação só dos pacotes que mudaram. A maioria dos times de biblioteca usa Changesets hoje.

Dá pra migrar de polyrepo para monorepo aos poucos?

Dá, e é o jeito recomendado. Você não precisa juntar tudo de uma vez. O caminho comum é criar o monorepo, mover primeiro as bibliotecas mais compartilhadas (preservando o histórico do Git com ferramentas de import), e ir trazendo os projetos conforme fizer sentido. Fazer um “big bang” migrando dez repositórios num fim de semana costuma dar errado. Migração incremental, medindo o CI a cada passo, é bem mais segura.

Conclusão

Monorepo não é uma bala de prata nem uma armadilha, é uma troca. Você ganha compartilhamento de código sem burocracia, mudanças atômicas que atravessam projetos e uma visibilidade que facilita onboarding e padronização. Em troca, assume a responsabilidade de manter fronteiras saudáveis, investir em CI de build afetado e cache, e lidar com os limites do Git quando o repositório cresce.

A decisão certa depende menos do que o Google faz e mais de como o seu código realmente muda. Se as suas mudanças vivem cruzando as fronteiras dos projetos e o time compartilha bastante coisa, o monorepo vai parecer que sempre deveria ter existido. Se os projetos são ilhas independentes, forçá-lo pra dentro de um repo só é criar dor sem retorno. Comece simples com os workspaces nativos, adote um build system como Turborepo ou Nx quando o CI reclamar, e deixe o Bazel pra quando a escala e o poliglotismo realmente pedirem. A melhor arquitetura de repositório é a que some do caminho e deixa o time entregar.

Para quem constrói sistemas que precisam de dados oficiais, o Hub do Desenvolvedor mantém APIs de consulta de CNPJ e CPF na Receita Federal prontas para você integrar sem burocracia.

Compartilhe nas mídias: