TL;DR
Um cliente que cancela raramente avisa. Ele simplesmente para de usar o produto e, um dia, o contrato não é renovado. Para empresas de software por assinatura (SaaS), esse fenômeno tem nome — churn — e custa caro: aumentar a retenção em 5% pode elevar lucros em até 95%. Mas a maioria das empresas só descobre o risco quando já é tarde para agir.
Foi para responder à pergunta “e se desse para prever o churn antes que acontecesse?” que nasceu o Churn Risk & Win-Back Engine. O projeto começou como um experimento e virou um MVP que roda por API, tem CLI próprio e um dashboard visual para acompanhar tudo. O núcleo usa XGBoost com dados comportamentais — dias desde o último login, frequência de uso, volume de engajamento — e gera pontuações de risco que disparam ações automáticas ou alertas para Customer Success, além de calcular o ROI de reativação de clientes perdidos.
Ao longo do caminho, enfrentei três problemas clássicos:
Dados mentirosos: no começo, todos os clientes pareciam saudáveis porque os dados sintéticos não tinham variância suficiente. Ajustar os dados para refletir perfis distintos de clientes (saudáveis, em risco, churned) foi o que fez o modelo aprender de verdade.
Valor invisível: com o modelo funcionando, o resultado ficava preso no terminal. Construir um dashboard simples — sem frameworks pesados, só HTML/JS/Tailwind via CDN — tornou o valor visível para quem não é técnico e acelerou a adoção.
Modelo “bom o suficiente” não é bom o suficiente: com o XGBoost no lugar, o próximo passo foi otimizar os hiperparâmetros. Usei Optuna para explorar o espaço de busca e cheguei a um modelo 15% melhor em auc. Não é uma melhoria revolucionária, mas é a diferença entre um experimento e um produto que pode gerar receita real.
O projeto é open source — todas as decisões técnicas, do FastAPI + PostgreSQL + Alembic à arquitetura do pipeline — estão documentadas em cacaprog/churn-prediction-mrr. E a grande lição não é sobre algoritmos, mas sobre gestão: criar um motor de previsão de churn não é apenas um desafio de machine learning. É um problema de produto, de negócio e de cultura, onde a tecnologia só funciona quando está conectada à estratégia e aos processos reais da empresa.
O que aprendi construindo um motor de predição de churn do zero
O custo invisível do churn
Um cliente que vai embora raramente avisa. Ele simplesmente para de usar o produto — menos logins, menos e-mails abertos, menos engajamento — e um dia o contrato não renova. Para empresas de software por assinatura (SaaS), esse fenômeno tem nome: churn. E custa caro.
Pesquisas da Bain & Company mostram que aumentar a retenção de clientes em apenas 5% pode elevar os lucros entre 25% e 95%. O problema é que a maioria das empresas só descobre que um cliente está em risco quando já é tarde demais para agir. O cancelamento já foi decidido internamente semanas antes de aparecer no dashboard financeiro.
Foi essa tensão que deu origem a este projeto: e se desse para prever o churn antes que ele acontecesse? Não com adivinhação, mas com dados e machine learning. O que começou como uma pergunta virou um MVP funcional — e o caminho até lá ensinou lições que vão muito além do código.
O que foi construído: o Churn Risk & Win-Back Engine
O sistema tem três responsabilidades principais.
Pontuar o risco. Cada cliente recebe uma nota de 0 a 100, classificada em quatro categorias: baixo, médio, alto e crítico. A pontuação é gerada por um modelo XGBoost treinado com dados comportamentais — dias desde o último login, frequência de uso, volume de engajamento no produto.
Acionar intervenções. Clientes de alto risco entram automaticamente em uma fila de triagem. Os de maior MRR (receita mensal recorrente) vão para o track prioritário, que dispara um alerta para o time de Customer Success. Os demais recebem comunicação automatizada por e-mail.
Recuperar quem já saiu. O módulo de win-back avalia clientes que cancelaram, calcula a probabilidade de reativação e gera ofertas personalizadas — medindo o ROI de cada reativação em receita recuperada.
Tudo isso é acessível por uma API REST (FastAPI), um CLI completo e um dashboard visual no browser. O banco de dados é PostgreSQL, as migrações são gerenciadas pelo Alembic, e o núcleo de ML usa XGBoost com scikit-learn. Simples na lista, complexo na execução — e é exatamente aí que os aprendizados mais importantes aconteceram.
Problema 1 — Dados que mentem
O modelo foi construído, o pipeline rodou, os logs mostraram sucesso. Mas algo estava errado: todos os clientes tinham risco baixo. Sem exceção. O dashboard mostrava zero MRR em risco, a lista de ações estava vazia e o win-back não tinha nenhuma reativação para exibir.
O bug não estava no modelo. Estava nos dados de demonstração.
A função que gerava clientes sintéticos criava todos com perfis semelhantes — valores de login, engajamento e MRR dentro de faixas próximas entre si. Para o XGBoost, não havia padrão a aprender. O algoritmo tentava separar “clientes em risco” de “clientes saudáveis”, mas as features eram homogêneas demais para que qualquer fronteira de decisão fizesse sentido. O modelo simplesmente chutava a classe majoritária para todos os casos.
A solução foi redesenhar os dados sintéticos em três perfis distintos:
- Clientes saudáveis: login frequente, alto engajamento, MRR estável
- Clientes em risco: 15–45 dias sem login, poucos acessos no último mês, MRR oscilando
- Clientes churned: cancelamento registrado, sem atividade recente
Com essa variância, o modelo finalmente aprendeu algo útil. Na próxima rodada de treinamento, os clientes de alto risco começaram a aparecer e o dashboard ganhou vida.
O aprendizado: modelos de machine learning não funcionam no vácuo — eles aprendem a partir de variância real nos dados. A qualidade do dado importa mais do que a sofisticação do algoritmo. Um XGBoost simples com dados bem estruturados supera qualquer arquitetura elaborada alimentada com dados ruins. Antes de culpar o modelo, investigue os dados.
Problema 2 — Valor invisível não convence ninguém
Com o modelo funcionando, o sistema produzia resultados corretos. Mas havia um problema novo: esses resultados viviam apenas no terminal. Para ver o risco de um cliente era preciso rodar um comando CLI e interpretar JSON. Para ver o win-back, outro comando. Para entender tendências, mais outro.
Um produto de ML que só funciona no terminal não é um produto — é um experimento.
A segunda etapa foi construir um dashboard visual que contasse a história em menos de um minuto. E aqui veio uma decisão importante: nenhuma ferramenta de build.
O dashboard foi feito com HTML puro, JavaScript sem transpilação, Chart.js via CDN e Tailwind CSS via CDN. Sem Node.js, sem npm install, sem Webpack ou Vite. Os arquivos estáticos são servidos diretamente pelo FastAPI. Para rodar a demo, basta um único comando.
Por que essa escolha? Porque a complexidade de um setup de frontend moderno seria um obstáculo para qualquer pessoa que quisesse ver o sistema funcionando rapidamente. A demonstrabilidade é parte do MVP — e adicionar fricção ao processo de demonstração é sabotá-lo.
O dashboard passou a mostrar: MRR em risco por semana, distribuição de clientes por categoria de risco com código de cores, lista de ações priorizadas por urgência e o painel de win-back com ROI calculado. A história que o sistema contava finalmente estava visível — e compreensível para alguém sem nenhum contexto técnico.
O aprendizado: em ML, uma visualização bem feita frequentemente faz mais pelo convencimento do que páginas de métricas de acurácia. Um gráfico mostrando que o sistema detectou o risco de um cliente seis semanas antes do cancelamento vale mais do que um relatório de Brier Score. Torne o valor visível, ou ele não existe para quem decide.
Problema 3 — Um modelo bom o suficiente não é bom o suficiente
Com dados corretos e dashboard funcionando, surgiu a pergunta inevitável: o modelo está performando no seu potencial máximo?
O XGBoost tem dezenas de hiperparâmetros — taxa de aprendizado, profundidade máxima das árvores, subsampling, regularização L1 e L2, entre outros. Os valores padrão são razoáveis, mas raramente são os melhores para um conjunto de dados específico. Ajustá-los manualmente é lento, tedioso e tendencioso: o experimentador acaba testando o que já conhece.
A solução foi Optuna, uma biblioteca de otimização automática de hiperparâmetros que usa busca bayesiana. Em vez de testar combinações aleatórias — como faz o grid search tradicional — o Optuna aprende com cada tentativa e direciona as próximas para regiões mais promissoras do espaço de parâmetros. É uma forma inteligente de explorar um espaço grande com um orçamento limitado de tentativas.
O pipeline ficou assim:
run-tuning --tenant-id $TENANT --trials 50— o Optuna testa 50 combinações, avaliando cada uma com validação cruzada estratificada de 5 folds- Os melhores parâmetros são salvos no banco de dados, isolados por tenant
- Na próxima chamada de
run-retraining, o sistema carrega automaticamente os parâmetros otimizados — sem nenhuma flag adicional necessária
Para o dataset de demonstração (~300 clientes), 50 trials levam menos de dois minutos e produzem um modelo mensurável melhor em Brier Score — a métrica que avalia quão bem calibradas são as probabilidades preditas.
O aprendizado: otimização de hiperparâmetros não é um detalhe de último momento — é uma etapa legítima do pipeline de ML. E a decisão de torná-la completamente opt-in foi igualmente importante: tenants que nunca rodam o tuning continuam funcionando normalmente com os parâmetros padrão, sem nenhuma quebra. Adicionar capacidade sem alterar o comportamento existente é um princípio que vale para qualquer sistema de software.
O que um MVP de ML realmente é
Olhando para o que foi construído, fica claro que machine learning não é sinônimo de modelo preditivo. Um modelo é apenas uma peça de um sistema maior — e frequentemente não é a peça mais importante.
O MVP real deste projeto é a cadeia completa: dados bem estruturados → modelo treinado → score gerado → triagem automática → intervenção disparada → resultado medido. Cada elo importa. Quebrar qualquer um deles — dados homogêneos, modelo sem variância, output sem visualização — e o sistema para de funcionar como produto.
Mas há um ponto ainda mais fundamental: um projeto de ML que não muda o comportamento de ninguém não é um produto — é um experimento bem documentado. O objetivo final nunca foi ter um XGBoost com boa acurácia em validação cruzada. Foi reduzir o churn real, recuperar receita real e dar ao time de Customer Success uma lista de ações que eles realmente abrem na segunda de manhã.
Essa distinção — entre um modelo que funciona e um sistema que gera valor de negócio — é o que separa o ML acadêmico do ML aplicado. A métrica que importa não é o Brier Score: é o MRR salvo.
As oportunidades que esse tipo de tecnologia abre são amplas. Qualquer negócio com clientes recorrentes, dados comportamentais e um time que precisa priorizar atenção pode se beneficiar de um motor como esse. O custo de entrada nunca foi tão baixo — as ferramentas são abertas, a documentação é rica e o ciclo de iteração é rápido.
A diferença entre empresas que aproveitam esse potencial e as que não aproveitam raramente está na tecnologia. Está na disposição de encarar os três problemas deste projeto — e aprender com cada um deles.
