
A pergunta sobre quando reescrever sistema legado quase nunca aparece em um momento calmo. Ela costuma surgir depois de um incidente, de uma janela de deploy tensa, de um p99 fora de controle ou de um time travado para entregar algo simples. Nessa hora, a ideia de jogar tudo fora e começar do zero parece racional. Na prática, muitas vezes é só exaustão técnica disfarçada de estratégia.
Sistema legado não é sinônimo de sistema ruim. Em muitos casos, é um sistema que sobreviveu ao crescimento do produto, acumulou integrações críticas e virou peça central da operação. O problema não é a idade do código. O problema é quando ele deixa de responder bem a mudanças, aumenta risco operacional e consome energia demais da equipe para manter o básico funcionando.
Quando reescrever sistema legado é uma decisão válida
Reescrita completa é uma medida extrema. Ela faz sentido quando o sistema atual se tornou estruturalmente incapaz de sustentar o negócio, e não apenas desconfortável para o time. Existe uma diferença grande entre código feio e arquitetura inviável.
O primeiro sinal real é quando a mudança custa caro demais de forma recorrente. Não estamos falando de uma sprint ruim. Estamos falando de meses em que qualquer ajuste simples exige tocar em módulos acoplados, validar fluxos obscuros e torcer para não quebrar faturamento, autenticação ou integrações. Se o lead time sobe, a taxa de rollback cresce e o time passa a evitar mexer em áreas críticas, o sistema já está impondo uma taxa operacional alta demais.
O segundo sinal é quando a plataforma não atende mais requisitos essenciais de negócio ou compliance e não há caminho economicamente viável para adequação incremental. Isso acontece em sistemas com modelo de dados incompatível com a operação atual, limitações graves de multi-tenant, problemas de isolamento entre clientes, trilha de auditoria insuficiente ou dependência de componentes sem suporte. Se adaptar custa quase o mesmo que reconstruir, a conversa muda.
Há também o caso em que o sistema perdeu observabilidade a ponto de se tornar opaco. Sem tracing, sem métricas confiáveis, sem telemetria por jornada crítica, cada incidente vira arqueologia. Quando ninguém consegue responder com segurança onde está o gargalo entre aplicação, fila, banco e dependências externas, a operação entra em modo reativo permanente. Ainda assim, falta de observabilidade sozinha raramente justifica reescrita. Normalmente ela aponta para um déficit de engenharia de plataforma, não para uma sentença arquitetural.
O que quase nunca justifica reescrever
Trocar stack por preferência de engenharia é um clássico. O sistema está em uma linguagem antiga, o time atual gosta de outra, e a discussão vira carreira e recrutamento. Isso é compreensível, mas não é tese de negócio. Reescrita motivada por moda tecnológica costuma gerar dois sistemas problemáticos em vez de um.
Outro erro comum é tentar resolver baixa velocidade de entrega com um projeto de reconstrução total. Parece contraintuitivo, mas a reescrita tende a reduzir velocidade por um bom tempo. Você cria uma segunda frente de desenvolvimento, duplica contexto, prolonga decisões estruturais e ainda precisa manter o legado vivo. Sem governança forte, o backlog do produto perde prioridade para um futuro que demora a chegar.
Também vale cortar um mito: performance ruim nem sempre pede reescrita. P99 alto pode vir de query mal indexada, uso incorreto de cache, fan-out excessivo entre serviços, falta de connection pooling, filas sem backpressure ou jobs concorrendo com tráfego online. Reescrever a aplicação sem atacar a causa só troca o formato do problema.
O custo escondido de começar do zero
Quem já operou produto em produção sabe: o maior ativo de um sistema legado não é o código, é o comportamento que ele já absorveu. Regras de negócio implícitas, exceções de integração, detalhes de billing, fluxos de suporte, dependências não documentadas. Tudo isso vive no sistema atual, mesmo que esteja mal representado.
Uma reescrita completa força o time a redescobrir esse conhecimento enquanto continua atendendo cliente, rodando deploy e respondendo pager. É aí que nascem os projetos que ficam 18 meses em paralelo e entregam menos do que prometiam. O sistema novo sai mais limpo, mas incompleto. O legado continua ali, agora com mais ressentimento acumulado.
Existe ainda o custo de validação. Reproduzir feature parity em sistemas complexos não é trivial. Mesmo quando a cobertura de testes parece boa, invariantes de produção costumam escapar. Dados históricos, integrações pouco usadas, contratos antigos de API e permissões específicas aparecem tarde. Se o plano de migração não estiver amarrado desde o início, o risco de cutover cresce rápido.
Como decidir com critério
A pergunta certa não é se o código está ruim. É se existe retorno mensurável em reconstruir uma parte relevante da plataforma em comparação com uma modernização guiada por risco e impacto.
Comece por quatro eixos: risco operacional, velocidade de entrega, custo total de manutenção e bloqueio de evolução do negócio. Se o sistema gera incidentes frequentes, exige esforço desproporcional para mudanças simples, consome cloud de forma ineficiente e impede movimentos estratégicos como expansão de produto, novos canais ou requisitos regulatórios, existe base para uma decisão maior.
Mas essa análise precisa sair do campo opinativo. Meça. Olhe para taxa de falha em deploy, MTTR, volume de retrabalho, throughput do time, hotspots de incidentes, custo por workload, saturação de banco, latência nas jornadas críticas e dependências sem suporte. Reescrever sem baseline é só trocar ansiedade por cronograma.
A alternativa que costuma funcionar melhor
Na maioria dos cenários de SaaS em crescimento, a melhor resposta não é reescrita completa. É decomposição orientada por domínio e risco. Você preserva o que ainda entrega valor, estrangula partes problemáticas e cria uma trilha de modernização com impacto incremental.
Isso pode significar extrair módulos com fronteiras mais claras, isolar fluxos de alta criticidade, redesenhar contratos entre componentes, mover cargas específicas para serviços mais adequados e atacar gargalos de dados antes de qualquer mudança estética de stack. Em paralelo, vale subir o nível de observabilidade, automação de deploy, testes de regressão e gestão de infraestrutura. Sem isso, o sistema novo herda a mesma fragilidade operacional do antigo.
Em muitos casos, a sequência correta é menos glamourosa e mais eficiente: primeiro estabilizar produção, depois medir, depois separar domínios, depois migrar capacidades de forma progressiva. Parece lento no papel, mas costuma gerar valor antes e reduzir risco de forma real.
Quando a reescrita parcial é o melhor caminho
Existe um meio-termo poderoso entre remendar tudo e reconstruir tudo. Reescrita parcial faz sentido quando há um núcleo claramente problemático que concentra incidentes, custo ou limitação arquitetural. Um motor de billing, um módulo de autenticação, um pipeline de processamento, uma camada de tenancy, uma API pública mal versionada.
Nesse cenário, o objetivo não é fazer cirurgia plástica no legado. É criar uma nova peça com fronteira operacional definida, telemetria adequada, testes e plano de migração controlado. O resto continua funcionando enquanto a parte crítica é substituída com critério.
Esse tipo de abordagem exige disciplina. Contratos precisam ser explícitos. Dados precisam de estratégia de migração e reconciliação. O rollout precisa ser gradual, com shadow traffic, feature flag ou dupla escrita quando fizer sentido. Sem isso, a reescrita parcial vira apenas mais um acoplamento escondido.
Sinais de que sua empresa não está pronta para reescrever
Se o time não consegue manter runbooks básicos, não tem observabilidade mínima por serviço, não possui ambiente confiável de testes e ainda depende de deploy manual sensível, reescrever agora tende a piorar a operação. O problema central não é o legado. É maturidade de engenharia.
Outro sinal ruim é ausência de dono claro para a decisão. Reescrita sem accountability sênior vira projeto paralelo eterno. Alguém precisa responder por escopo, critérios de sucesso, impacto no produto, risco de migração e continuidade do sistema atual. Sem essa liderança, o projeto deriva.
Também desconfie quando o argumento principal é moral. Frases como “ninguém aguenta mais esse código” ou “precisamos limpar tudo” revelam dor real, mas não definem estratégia. A decisão precisa ser sustentada por capacidade, risco e economia operacional.
O que um plano maduro deveria conter
Se a conclusão for reescrever, o plano precisa ser duro com a realidade. Escopo limitado, hipóteses explícitas, métricas de saída e convivência planejada com o legado. Não existe cenário sério em que um sistema crítico de SaaS some hoje e um novo apareça amanhã sem fase de transição.
Um bom plano define o que será refeito, o que continuará igual, quais comportamentos precisam ser preservados, como a migração de dados ocorrerá e quais checkpoints validam que a aposta segue racional. Também deixa claro o custo de oportunidade. Cada squad alocado em reescrita é capacidade que sai de roadmap, reliability ou crescimento.
É exatamente aí que uma consultoria sênior faz diferença. Não para vender replatforming como troféu, mas para separar problema de sintoma, medir o terreno e executar a mudança certa. Em muitos clientes, a resposta honesta é não reescrever. Em outros, é reescrever um pedaço pequeno e crítico. E, em poucos casos, é aceitar que o sistema atual já passou do ponto.
Reescrever sistema legado é menos sobre coragem e mais sobre precisão. O time maduro não escolhe a opção mais bonita no quadro. Escolhe a que reduz risco, devolve velocidade e sustenta produção sem teatro. Se você ainda não tem evidência suficiente para uma decisão extrema, o próximo passo não é começar um novo repositório. É enxergar melhor o sistema que já paga a conta.