Voltar para o Blog
Construindo em Público3 / 10
Construindo em PúblicoParte 3 de 10

Um monorepo, muitas áreas de produto, sem virar caos

4 min de leitura
Compartilhar
Construindo em Público

O ClubPetro não é um produto. São uns dezesseis. Customer Success, Finance, Support, Marketing, Sales, Admin, Platform, Tech, e por aí vai — cada área com suas telas, suas regras, seu público interno. E tudo isso vive num monorepo só. Quando a gente conta isso, a reação comum é: "não vira um caos?" A resposta honesta é que poderia virar, e a diferença entre caos e alavanca está em algumas decisões de fronteira que a gente leva a sério.

Por que um monorepo, e não dezesseis repositórios

A tentação de separar é real. Cada área parece um produto independente; por que não dar a cada uma seu repositório, seu deploy, sua vida?

Porque o custo de separar, para um time pequeno, é maior do que o custo de conviver. Num monorepo:

  • Uma mudança atravessa camadas num commit só. Precisou de um campo novo no banco, uma regra nova no domínio, uma procedure e uma tela? É um PR, não seis, sincronizados entre seis repositórios com versões que nunca batem.
  • O compartilhamento é de graça. Um componente de tabela feito para o Finance está imediatamente disponível para o Sales. Sem publicar pacote, sem bump de versão, sem esperar o outro time atualizar a dependência.
  • A refatoração é possível. Renomear um conceito que aparece em dez áreas é uma operação atômica. Em repositórios separados, seria uma campanha.

Para um time grande com dezenas de squads independentes, a matemática muda. Para o nosso, o monorepo é o que deixa poucas pessoas moverem muita superfície.

As fronteiras que impedem o caos

Monorepo sem disciplina de fronteira vira uma bola de lama grande. O que segura a nossa é a separação clara entre pacotes compartilhados e áreas de produto.

Os pacotes compartilhados são a fundação:

  • packages/ui — o design system, com dezenas de componentes sobre Radix. Toda área consome daqui. É o que faz o Finance e o Support parecerem o mesmo produto, mesmo construídos em semanas diferentes por pessoas diferentes.
  • packages/db — o acesso a dados via Drizzle, um lugar só que fala com o Postgres. Ninguém instancia cliente de banco solto; todo mundo passa pelos singletons.
  • packages/domain — a lógica de negócio pura, sem I/O. As regras que valem para toda a empresa moram aqui, não espalhadas pelas telas.
  • packages/shared, packages/ai, packages/messaging — tipos comuns, os agentes Claude, e o envio de e-mail e WhatsApp.

A regra que mantém isso são: as áreas de produto dependem dos pacotes compartilhados, nunca o contrário, e uma área não fura a fronteira da outra. O Sales não importa direto o código interno do Finance. Se os dois precisam da mesma coisa, essa coisa sobe para um pacote compartilhado. É a diferença entre reúso saudável e acoplamento acidental.

O que trava e como a gente lida

Não é tudo idílico. Monorepo grande tem seus atritos, e vale ser honesto sobre eles:

  • O typecheck de uma área grande estoura memória. É uma realidade da nossa base; a gente convive dando mais memória ao processo em vez de fingir que não existe.
  • Existe um baseline de erros de tipo pré-existentes que o build tolera de propósito. A disciplina aqui é não confundir "erro que já existia" com "erro que eu acabei de introduzir". O que importa é o delta, não o zero absoluto.
  • CI só roda o que foi afetado. Um PR que mexe só no Marketing não paga o custo de buildar o Finance inteiro. O turbo com filtro por pacotes afetados é o que mantém o feedback rápido mesmo com a base crescendo.

Nenhuma dessas fricções justifica quebrar o monorepo. Cada uma tem uma mitigação que custa menos do que a alternativa de sincronizar dezesseis repositórios.

Por que isso importa para quem constrói aqui

Um monorepo bem cuidado é um multiplicador para time pequeno. Você toca uma área de manhã e outra à tarde sem trocar de contexto de ferramenta, sem clonar outro repositório, sem descobrir que a versão do design system que aquele time usa é três atrás. A superfície é grande, mas a distância entre qualquer dois pontos dela é curta.

O builder que prospera nesse ambiente é o que respeita fronteira sem se esconder atrás dela. Que sabe quando uma coisa pertence à sua área e quando ela precisa subir para um pacote compartilhado porque outra área também vai querer. Que enxerga o sistema inteiro, não só o próprio canto. Num monorepo, o código de todo mundo é, em algum grau, o código de todo mundo — e é justamente isso que deixa a gente andar rápido sem se atropelar.

Curtiu como a gente pensa?

É assim que trabalhamos todo dia.

Se esse jeito de pensar é o seu, vem construir com a gente — dá uma olhada nas vagas abertas.

Ver vagas