← Projetos Leonardo Borges Ramos

Case · Develop ERP

Um ERP, dezenas de empresas, nenhuma parada.

Como construí e mantenho o sistema de gestão da Develop Sistemas: web, Windows e iPhone sobre a mesma API, com cada empresa isolada no seu próprio esquema do banco.

Papel
Fundador e engenheiro: arquitetura, API, telas, apps, deploy
Período
2024 → hoje, em produção
Stack
React · Node.js · Express · MySQL (Azure) · Tauri/Rust · React Native/Expo · Vercel · Railway
Números
15.262 commits¹ · 4.506 rotas de API¹ · 339 arquivos de rota¹ · ~90 esquemas no servidor²

O problema

Indústrias, distribuidoras, óticas e lojas usavam um ERP antigo, montado em Appsmith, com mais de 160 telas: lento, difícil de mudar e preso a uma plataforma de terceiros. Elas não podiam parar de vender durante a troca, e o banco já tinha dezenas de clientes em produção, todos com o mesmo formato de tabelas.

Meu papel

Sou o fundador da Develop e quem escreve a maior parte do código: arquitetura, API, telas web, o app de Windows, o de iPhone, deploy e suporte de segundo nível. Trabalho com um time pequeno e uso agentes de IA como par de programação, com regras escritas para o que nunca pode acontecer sem pedido explícito, como mudar a estrutura do banco compartilhado.

A arquitetura

Três decisões, e o porquê

1. Um esquema de banco por cliente, no mesmo servidor

Os clientes já existiam assim no sistema antigo. Juntar todos num banco só, com uma coluna de empresa em cada tabela, exigiria migrar e parar todo mundo. Mantendo um esquema por cliente, o isolamento vem da construção e não de um filtro que alguém pode esquecer: uma empresa não enxerga a outra porque a consulta nem roda no esquema dela.

O preço: o servidor é compartilhado por dezenas de empresas, então qualquer mudança de estrutura só acontece com pedido explícito. É regra escrita do projeto, inclusive para os agentes de IA.

2. A venda nasce no disco (PDV offline)

Quando a internet cai, o caixa não pode parar. No app de Windows cada venda é gravada primeiro num diário só de acréscimo, com fsync, escrito em Rust; depois entra numa fila que um agente envia a cada 90 segundos. Cada venda guarda o número oficial que o servidor deu a ela e, antes de fechar de novo, o caixa confere se ela já foi finalizada: reenviar nunca cobra duas vezes. A venda online e a sincronizada passam pela mesma função de gravação, então não existem duas regras de venda para manter.

O preço: o caixa precisa de um catálogo local e de um selo que mostre o que ainda não subiu, para ninguém confiar num número que o servidor ainda não viu.

Detalhe no case do PDV offline.

3. Trocar o sistema antigo tela por tela, com ele no ar

Uma troca de uma vez pararia dezenas de empresas no mesmo dia. Cada tela nova lê as mesmas tabelas, com os nomes exatos do esquema real, e o cliente passa a usá-la quando ela fica pronta. O sistema antigo e o novo convivem sem migração de dados.

O preço: conviver com os nomes de coluna do legado em vez de redesenhar o banco do zero.

O que deu errado

Um controle de acesso registrado sem caminho (router.use()) passou a valer para todos os módulos montados depois dele: 13 módulos responderam "acesso negado" por uma hora e meia. Hoje um teste automático barra esse padrão antes de qualquer publicação.

O que eu faria diferente

¹ Medido em 20/10/2026 no repositório do ERP (git rev-list --count; git grep de router.get/post/put/patch/delete em api/src; arquivos em api/src/routes).

² Contagem de esquemas no servidor MySQL em 09/10/2026; inclui esquemas internos e de sistema.

Quer conversar sobre este projeto?