O padrão strangler fig para migrações legacy
Rewrites big-bang apostam tudo em uma data. O padrão strangler fig vence roteando tráfego endpoint por endpoint — construindo o sistema novo ao redor do antigo até o núcleo legacy ficar oco e seguro de remover.
O rewrite levava dezoito meses. Chegou a data de lançamento. O tráfego mudou. Três semanas depois, o tráfego voltou. O sistema novo tratava happy paths; edge cases viviam só no codebase legacy que ninguém tinha mapeado por completo. Integrações de folha de pagamento, overrides de admin, códigos promocionais de dez anos — a aposta big-bang de que uma data no calendário podia substituir verdade incremental. Strangler fig legacy migration faz a aposta oposta: rotear uma capacidade por vez, provar cada slice em produção, manter rollback trivial até o sistema antigo não ter mais nada a fazer.
O padrão nomeia uma figueira que cresce ao redor de uma árvore hospedeira, eventualmente substituindo-a. Em software: uma fachada ou router fica na frente do sistema legacy. Novas implementações absorvem endpoints, eventos ou caminhos de dados. O núcleo legacy encolhe até descomissionamento ser um projeto pequeno, não um evento de risco para toda a empresa.
Rewrites big-bang falham em unknown unknowns
| Risco big-bang | Por que se compõe |
|---|---|
| Regras de negócio ocultas | Só surgem sob edge cases em produção |
| Desenvolvimento paralelo | Legacy continua mudando durante o rewrite |
| Lacunas no inventário de integrações | Consumidores não documentados aparecem no cutover |
| Rollback tudo-ou-nada | Reverter é tão arriscado quanto o lançamento |
| Queda de moral | Longos períodos escuros antes da validação |
Rewrites parecem limpos em diagramas de arquitetura. São bagunçados em backlogs de tickets, SLAs de parceiros e auditorias de compliance. O strangler fig aceita bagunça de antemão — sistemas duais, complexidade de roteamento, duplicação temporária de dados — em troca de entrega contínua de valor e passos reversíveis.
Uma migração sem rollback por passo é um rewrite disfarçado de plano de projeto.
Anatomia de uma migração strangler fig
Fachada / router. Ponto de entrada único para clientes — API gateway, reverse proxy ou router de aplicação. Todo tráfego passa por ali. Regras de roteamento decidem implementação legacy vs nova por endpoint, feature flag ou tenant.
Seleção de slice. Escolher limites com inputs e outputs claros — um recurso REST, um tipo de evento, um batch job. Não "o módulo de billing" — POST /invoices, evento InvoiceCreated, job noturno de reconciliação.
Nova implementação. Construir atrás da fachada. Modo shadow opcional: sistema novo processa requests mas não responde a clientes — comparar outputs antes do cutover.
Mudança de tráfego. Por porcentagem, por tenant ou cutover completo por slice. Feature flags controlam roteamento sem redeploy da fachada.
Encolhimento do legacy. Remover código roteado do legacy só após prova sustentada — métricas verdes, sem rollback por N dias, reconciliação limpa.
Descomissionamento. Quando legacy trata zero tráfego de produção e não há dependências batch, aposentar infraestrutura.
Clients → Facade/Router
├─ /users/* → New User Service
├─ /orders/* → New Order Service
├─ /reports/* → Legacy Monolith
└─ /admin/* → Legacy Monolith (last)
O artigo sobre arquitetura modular monolith para startups descreve limites internos de módulos que viram slices naturais de strangler — extrair um módulo para serviço sem reescrever a aplicação inteira.
Migração de dados é a parte difícil que roteamento não resolve
Rotear tráfego HTTP é a camada visível. Dados costumam sobreviver ao código.
| Padrão de dados | Abordagem strangler |
|---|---|
| Slice read-heavy | Novo serviço lê réplica; legacy ainda escreve até cutover |
| Migração de escrita | Período dual-write — ambos sistemas aceitam escritas, job de reconciliação compara |
| Sync event-driven | Legacy emite eventos de mudança; sistema novo constrói read model |
| Anti-padrão de banco compartilhado | Extrair slice de schema para DB nova com sync; último recurso são tabelas compartilhadas com ownership estrito |
Períodos dual-write precisam de reconciliação — comparar contagens de linhas, checksums, diffs de amostra em schedule. Divergência descoberta no descomissionamento é cara. Divergência descoberta toda noite é gerenciável.
Nunca deletar caminhos de dados legacy até o caminho novo ter processado tráfego de produção por um ciclo de negócio completo — fechamento de mês, ciclo de billing, janela de reporting de compliance.
Estratégia de ordenação de slices
Nem todo endpoint é candidato igual de migração.
Migrar primeiro:
- Domínios de alto churn e bem entendidos com boa cobertura de testes
- Caminhos read-heavy onde escritas legacy defasadas sejam toleráveis brevemente
- Features bloqueando nova direção de produto
- Endpoints com poucos consumidores não documentados
Migrar por último:
- Caminhos de admin e override com regras de negócio implícitas
- Batch jobs com dependências de calendário
- Integrações com parceiros externos que exigem recertificação
- Áreas onde o "como funciona" vive na cabeça de um único engenheiro
Cada slice shipa de forma independente. Celebrar conclusão de slice — não só descomissionamento final. Moral sobrevive a prova incremental.
Operações de fachada: roteamento, observabilidade, rollback
A fachada é infraestrutura de produção. Tratá-la como tal.
- Config de roteamento como código — regras versionadas, mudanças revisadas, trilha de auditoria.
- Métricas por rota — latência, taxa de erro, divisão de tráfego legacy vs novo.
- Rollback instantâneo — virar flag ou regra de roteamento para 100% legacy em um slice sem afetar outros.
- Rastreamento de requests — correlation ID através da fachada até implementação; essencial para comparação em shadow mode.
Feature flags como infraestrutura de release se sobrepõe ao roteamento strangler — flags controlam qual implementação serve tráfego. A diferença é intenção estratégica: flags compuertam features; flags strangler compuertam substituição arquitetural.
Como equipes devem planejar uma migração strangler fig?
Essas perguntas evitam fachadas que viram complexidade permanente.
Quando strangler fig é melhor que rewrite?
Quando legacy está em produção com usuários reais, regras ocultas e integrações que não podem pausar. Quando o time precisa shipar novas capacidades durante a migração. Quando rollback por slice é requisito. Rewrite pode servir substituição greenfield sem dependência de produção — raro em sistemas maduros.
Quão pequeno deve ser um slice?
Pequeno o bastante para rollback em uma mudança de roteamento. Grande o bastante para entregar valor significativo. Típico: um grupo de recursos API, um consumidor de eventos, um job agendado — semanas a meses, não dias ou anos.
O que impede a fachada de virar permanente?
Rastrear porcentagem de tráfego legacy por rota. Definir critérios de descomissionamento de antemão: "tráfego legacy /orders = 0 por 30 dias." Fachadas sem métricas de sunset viram operação de sistemas duais para sempre.
Um argumento comum vai na direção oposta
A visão oposta sustenta que manter dois sistemas custa mais que um rewrite rápido — que strangler fig prolonga dor e duplica esforço.
Custo de sistemas duais é real e deve ser orçado. Custo de falha big-bang — reverter, meses perdidos, impacto em clientes — é maior e menos previsível. Strangler fig limita downside por slice. O tempo total em calendário pode exceder um big-bang bem-sucedido, mas big-bangs que falham não têm tempo total em calendário — têm um reinício.
Times com capacidade limitada se beneficiam justamente porque slices cabem em sprints normais junto com trabalho de features. Rewrites consomem o roadmap.
Key takeaways
- Strangler fig migra um endpoint ou capacidade por vez atrás de um router fachada.
- Rewrites big-bang falham em edge cases e integrações descobertas só no cutover.
- Dual-write de dados e reconciliação importam tanto quanto roteamento de tráfego.
- Migrar primeiro slices read-heavy bem entendidos; admin e batch jobs por último.
- Rollback por slice via flags de roteamento mantém migração reversível.
- Rastrear tráfego legacy por rota — fachadas sem métricas de sunset viram permanentes.
Conclusion
Migração legacy não é um projeto com linha de chegada em um Gantt. É uma sequência de pequenas provas de que o sistema novo pode carregar verdade de produção — um slice por vez, com o sistema antigo ainda de pé até cada prova se sustentar.
O primeiro passo não é escrever código novo. É inventário: listar cada entry point ao sistema legacy, medir tráfego e risco por rota, escolher o slice de maior valor mais pequeno e colocar um router na frente. A figueira cresce dali.