Uma primeira versão pequena costuma ser a escolha certa. O risco surge quando a velocidade inicial vira arquitetura acidental: controllers decidem tudo, consultas se duplicam, estados são texto livre e automações alteram registros sem aplicar as mesmas regras.
A alternativa não exige microsserviços. Para muitas equipes, um monólito modular bem projetado oferece limites claros de domínio, uma única unidade implantável e disciplina suficiente para crescer.
1) Modular não significa agrupar arquivos por tipo
Pastas de controllers, services e models organizam o código, mas não definem responsabilidades de negócio. Um módulo útil representa uma capacidade: solicitações, aprovações, faturamento, estoque ou identidade.
Cada módulo deve expor casos de uso deliberados e proteger suas invariantes. Outros módulos não deveriam atualizar suas tabelas diretamente apenas porque compartilham o PostgreSQL.
2) Quatro camadas com responsabilidades verificáveis
| Camada | Responsabilidade | Sinal de alerta |
|---|---|---|
| Interface / API | Autenticar, validar formato e traduzir solicitações | Contém decisões financeiras ou operacionais |
| Aplicação | Coordenar o caso de uso e a transação | Depende de HTTP ou detalhes da tela |
| Domínio | Estados, regras e invariantes | As regras existem apenas nos formulários |
| Infraestrutura | Persistência, e-mail, arquivos e APIs externas | Um fornecedor dita o modelo de negócio |
3) O banco de dados também protege o processo
TypeScript reduz erros no desenvolvimento; não evita escritas concorrentes nem dados inseridos por outro canal. Chaves estrangeiras, restrições únicas, tipos adequados e transações devem sustentar regras que não podem ser violadas.
Prisma facilita acesso tipado e migrações, mas o esquema continua sendo uma decisão de produto. Índices, cardinalidade, bloqueios e planos de migração precisam de revisão; o ORM não substitui o projeto de dados.
4) Modelar comandos e consultas separadamente
Uma tela operacional pode precisar de uma consulta agregada e otimizada. Aprovar uma solicitação exige verificar permissões, estado atual e regras de transição. Forçar os dois caminhos pelo mesmo objeto cria acoplamento desnecessário.
Não é preciso adotar CQRS completo. Distinguir leituras orientadas às telas de comandos que alteram estado já permite otimizar relatórios sem enfraquecer as regras de escrita.
5) Transações curtas; efeitos externos depois
Enviar e-mail ou chamar uma API dentro de uma transação mantém bloqueios enquanto outro sistema responde. Uma abordagem mais robusta grava a mudança e um evento pendente na mesma transação; um worker processa a notificação depois com idempotência e retentativas.
n8n pode orquestrar tarefas externas quando traz visibilidade operacional. O backend mantém a autoridade sobre estados e regras; o workflow recebe eventos e devolve resultados por contratos explícitos.
6) Permissões pertencem às ações, não apenas às telas
Ocultar um botão melhora a experiência, mas não é controle de acesso. O backend deve autorizar cada comando conforme identidade, papel, escopo e estado do registro. Ações sensíveis devem registrar ator, momento, motivo e valores relevantes antes e depois.
7) Contratos e erros que ajudam a operação
Uma API sustentável usa esquemas versionáveis, códigos de erro estáveis e um identificador de correlação. O usuário precisa saber o que corrigir; o suporte precisa localizar o percurso; a engenharia precisa de contexto sem expor segredos.
- Erros de validação com campos e regras compreensíveis.
- Conflitos de versão quando outro usuário alterou o registro.
- Resultados idempotentes para comandos repetidos.
- Logs estruturados conectados ao caso, evento e ator.
8) Testar as fronteiras de risco
Cobertura total é menos valiosa que testes deliberados de invariantes: transições inválidas, concorrência, permissões, arredondamentos, duplicatas e retentativas. Integrações externas exigem testes de contrato e cenários de timeout ou resposta parcial.
9) Um caminho incremental
- Definir módulos a partir das capacidades e dos responsáveis pelo processo.
- Escolher um fluxo crítico e documentar estados, invariantes e permissões.
- Encapsular seus casos de uso antes de reorganizar todo o sistema.
- Apoiar regras críticas com restrições e transações.
- Mover efeitos externos para uma fila ou padrão outbox.
- Medir erros, tempos e exceções antes de separar implantações.
10) Sustentabilidade é a capacidade de mudar com controle
Uma boa arquitetura interna não tenta prever todos os requisitos. Ela torna as regras fáceis de localizar, limita o impacto de mudá-las e deixa evidência quando o processo evolui.
Node.js, TypeScript, PostgreSQL e Prisma oferecem uma base produtiva. A vantagem aparece quando a estrutura técnica reflete responsabilidades operacionais reais, permitindo crescer sem transformar cada nova tela em dívida futura.