Monorepo e polirrepo
Monorepo é um repositório com vários projetos que compartilham histórico, versão e processo. Não é “todo o código da empresa num lugar só” — é uma decisão sobre onde fica a fronteira de coordenação. E, como toda fronteira, ela move o custo em vez de eliminá-lo.
O que muda no dia a dia
Seção intitulada “O que muda no dia a dia”| Monorepo | Polirrepo | |
|---|---|---|
| Mudança que atravessa serviços | Um PR, atômico | Vários PRs, ordem e coordenação |
| Reuso de biblioteca interna | Import direto, sempre atualizado | Publicar versão, atualizar consumidores |
| Refatoração ampla | Viável (ferramenta vê tudo) | Cara, feita em ondas |
| CI | Precisa de build afetado | Simples e naturalmente isolado |
| Permissão por time | Por caminho (CODEOWNERS) | Nativa, por repositório |
| Autonomia de versões | Baixa: todos no mesmo tronco | Alta: cada um no seu ritmo |
| Ferramentas Git | Sofrem com repositório grande | Sem problema |
O ganho central do monorepo é a mudança atômica: alterar o contrato e todos os consumidores no mesmo commit, com o CI verificando o conjunto. O custo central é que você precisa construir a infraestrutura que o polirrepo dá de graça — build afetado, isolamento de permissão, ferramenta de release.
Build afetado é obrigatório
Seção intitulada “Build afetado é obrigatório”Rodar tudo a cada commit é o que faz monorepo ter fama de CI lento. A saída é calcular o grafo de dependências e executar só o que a mudança alcança.
# Nx: o que mudou em relação ao tronco, e o que depende dissonpx nx affected -t build,test,lint --base=origin/main
# Turborepo: com cache remoto, o que não mudou nem executanpx turbo run build test --filter='...[origin/main]'O que faz isso funcionar de verdade:
- Cache remoto compartilhado entre CI e máquinas locais — a maior economia isolada.
- Tarefas determinísticas: mesma entrada, mesma saída. Passo que lê data, rede ou estado global destrói o cache.
- Fronteiras declaradas: cada projeto declara suas dependências; import fora do grafo quebra o cálculo do afetado e precisa ser barrado por lint.
Sem affected e cache, o monorepo cobra o preço do acoplamento sem entregar a velocidade.
Ferramentas
Seção intitulada “Ferramentas”- Turborepo — simples, cache remoto bom, ótimo para JavaScript/TypeScript.
- Nx — grafo rico, geradores, análise de fronteiras; mais opinativo.
- Bazel / Pants — reprodutibilidade forte e suporte poliglota, para escala grande; curva alta e custo de manutenção real.
- Changesets — versionamento e changelog de pacotes dentro do monorepo.
- Para repositório muito grande, o Git tem
sparse-checkoute clone parcial (--filter=blob:none), que resolvem a lentidão local.
Comece pelo mais simples que resolve. Bazel é excelente e é um projeto de plataforma; não é o primeiro passo de ninguém.
CI em monorepo sem esperar quarenta minutos
Seção intitulada “CI em monorepo sem esperar quarenta minutos”jobs: afetados: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } # o cálculo precisa do histórico - run: npx turbo run lint test build --filter='...[origin/main]'Além do afetado e do cache, três ajustes cortam a maior parte do tempo restante: paralelizar por projeto em matriz, separar verificação rápida (lint, tipos, unitário) de verificação lenta (integração, e2e) em etapas distintas, e aplicar merge queue para o tronco não quebrar com merges concorrentes.
E um detalhe de deploy: em monorepo, o gatilho de deploy precisa ser por caminho alterado, ou todo merge publica tudo.
Quando dividir
Seção intitulada “Quando dividir”Nem sempre a resposta é juntar tudo. Divida quando:
- O ciclo de vida é genuinamente independente (produto de terceiro, ferramenta interna isolada).
- A exigência de permissão é forte — código com restrição de acesso não deve ficar no mesmo repositório de todo mundo.
- A stack não compartilha ferramenta nenhuma e a “vantagem” seria só a pasta comum.
- Open source: o público precisa ver aquele projeto, e não o resto.
E o meio-termo mais comum na prática brasileira funciona bem: um monorepo por domínio ou por time, com bibliotecas compartilhadas publicadas por versão. Você fica com mudanças atômicas onde elas acontecem de verdade — dentro do domínio — sem construir plataforma de build para a empresa inteira.
Qualquer que seja a escolha, o que separa o resultado bom do ruim não é a topologia: é ter CI rápido, fronteiras explícitas e uma forma clara de saber quem é dono do quê.
Próximo passo: você fechou a trilha de Versionamento. Leve isso ao pipeline em Anatomia de um pipeline e acelere a verificação com Acelerar pipeline lento.