githublinkedinemail
← /articles

Refatorar monólito sem detonar produção

Microsserviço não é a solução. Refatorar monólito é uma arte — strangler fig, feature flag, migração de schema em passos. O que ninguém te conta sobre o processo.

5 minarchitecture

Refatorar monólito sem detonar produção

Existe uma mentira que LinkedIn adora repetir:

"Migre seu monólito pra microsserviços."

Não.

90% dos casos: você deveria refatorar o monólito.

Não dividir.

E refatorar monólito grande é uma arte específica — que ninguém ensina porque "não é sexy".


Primeiro: por que refatorar?

Refatorar não é "deixar bonito".

Refatorar é:

  • reduzir tempo de onboarding de devs novos
  • reduzir bug rate
  • aumentar velocidade de entrega
  • aumentar confiança em mudanças

Se não tem dor de ENTREGA, talvez não precise refatorar agora.

Refatoração sem dor real é vaidade técnica.


A regra número 1: testes antes de tudo

Você não refatora código sem teste.

Você reescreve. E reescreve quebra.

Se a área que você quer mexer não tem cobertura:

  1. Para. Escreve teste pra comportamento atual.
  2. Garante que passa.
  3. Aí refatora.
  4. Roda teste a cada mudança pequena.

Isso é o "boy scout rule" reverso: deixe a base testada antes de partir pra ação.


Strangler Fig — a estratégia que funciona

Termo cunhado pelo Martin Fowler.

Ideia: você não substitui o sistema todo de uma vez. Você cresce algo novo ao redor do antigo, e vai migrando rota por rota até o velho ser apenas uma casca.

[Cliente]
   ↓
[Router]
   ├── rota A → código novo
   ├── rota B → código novo
   ├── rota C → código antigo
   └── rota D → código antigo

Com o tempo, todas as rotas migram. Você apaga o velho.

Estratégia oposta: big bang rewrite. Falha em 90% dos casos.


Inventário antes da ação

Antes de tocar em código, mapeie:

  • quais módulos existem
  • quais dependem de quais
  • quais têm cobertura de teste
  • quais mudam com mais frequência (git log frequency)
  • quais geram mais bugs (issue tracker)

Cruze essas três últimas: alta mudança + alto bug + baixa cobertura = comece por aqui.

Esse é o ROI maior.


Padrões pra extrair contexto

1. Domain object

Substitua "service class fofa" por objeto de domínio com identidade própria.

# antes
UserService.process(user, params)

# depois
PaymentRequest.new(user: user, amount: amount).submit

Não é só renomeação. É deslocar comportamento pra onde ele pertence.

2. Value object

Tudo que é "primitivo cercado de regra" merece ser objeto:

# antes — Money espalhado como integer
total_in_cents = price * quantity
formatted = "R$ #{total_in_cents / 100.0}"

# depois — Money class
total = Money.new(price) * quantity
formatted = total.format(:brl)

Encapsula regra. Reduz bug. Permite reuso.

3. Bounded context

Inspirado em DDD. Não precisa virar microsserviço — pode ser apenas namespacing rigoroso:

app/
├── billing/
│   ├── invoice.rb
│   ├── payment.rb
│   └── subscription.rb
├── catalog/
│   ├── product.rb
│   └── category.rb
└── identity/
    ├── user.rb
    └── session.rb

Cada pasta = um contexto. Comunicação entre eles via interface explícita, não via cross-reference direto.

Isso é tudo que "modular monolith" significa.


Feature flag é o segundo melhor amigo

Quer migrar uma rota crítica? Não troque tudo de uma vez.

if Flag.enabled?(:new_checkout, user)
  NewCheckout.process(order)
else
  OldCheckout.process(order)
end

Rola para 1% dos users. Mede. Aumenta. Mede. Aumenta.

Quando 100% rodou tranquilo por X semanas, apaga o antigo.

Sem feature flag: ou você lança e reza, ou cria branch de longa vida que vira pesadelo de merge.


Migrações de banco precisam de cuidado triplo

Refatorar código é uma coisa. Migrar schema é outra.

Regras:

1. Mudança quebrante = vários deploys.

Passo 1: adiciona coluna nova (compatível com código atual)
Passo 2: aplicação começa a escrever na coluna velha E na nova
Passo 3: backfill da coluna nova
Passo 4: aplicação lê da coluna nova
Passo 5: para de escrever na velha
Passo 6: dropa a velha

Cada passo é deploy separado.

2. Nunca adicione coluna NOT NULL sem default em tabela grande.

Lock total. Aplicação trava.

3. Cuidado com ALTER TABLE em tabela com milhões de linhas.

Use pg_repack, strong_migrations gem, ou estratégias específicas do seu banco.


O cemitério de código

Antes de refatorar, descubra o que pode morrer.

Ferramentas:

  • rubocop com regra de Lint/UselessAssignment
  • coverage rodando em produção (gem coverband)
  • log de uso de endpoint (se ninguém chama há 6 meses, considere deletar)

Refatorar código morto é desperdício.

Apague antes.


O que não fazer

  • Reescrever do zero sem entender o sistema atual.
  • Refatorar várias áreas em paralelo (cada uma vira branch infernal).
  • Refatorar e adicionar feature no mesmo PR.
  • Fazer "limpeza" sem teste de regressão.
  • Sair do escopo do PR pra "consertar mais coisas".

Refatoração é cirurgia. Não é faxina.


Métricas pra acompanhar

Antes da refatoração:

  • lead time (PR aberto → produção)
  • bug rate por área
  • tempo de onboarding
  • coverage por contexto

Depois:

  • mesmas métricas
  • comparar
  • mostrar pra liderança que valeu a pena

Sem métrica, refatoração vira "ele fica mexendo em código velho ao invés de entregar feature".

E aí você perde o orçamento político pra continuar.


A grande virada de chave

Refatorar monólito não é destruir e reconstruir.

É:

  • escolher onde tem ROI real
  • proteger com teste
  • mudar em pequenos pedaços
  • usar feature flag pra de-risk
  • medir antes e depois

Quem segue isso, refatora monólitos enormes com confiança.

Quem ignora, reescreve achando que "vai ser rápido" — e leva 2 anos no que deveria ser 3 meses.


Conclusão

Monólito não é o vilão.

Monólito mal cuidado é.

Microsserviço não é a solução. É um trade-off com custos enormes — operacional, de complexidade, de latência, de debug.

A maturidade técnica é entender que:

  • monólito modular bem feito vence microsserviços mal feitos
  • refatoração consistente vence reescrita revolucionária
  • contexto bem desenhado vence service crap espalhada

Refatorar bem é menos sobre código, e mais sobre disciplina de processo.

Quem aprende isso muda a carreira inteira.


Refatorar monólito sem detonar produção
Refatorar monólito sem detonar produção