[{"data":1,"prerenderedAt":1285},["ShallowReactive",2],{"article-\u002Fsistemas\u002Fmigrar-monolito-para-microservicos":3},{"id":4,"title":5,"author":6,"body":7,"category":1269,"date":1270,"description":1271,"extension":1272,"keywords":1273,"meta":1279,"navigation":406,"path":1280,"seo":1281,"slug":1282,"stem":1283,"updated":1270,"__hash__":1284},"content\u002Fsistemas\u002Fmigrar-monolito-para-microservicos.md","Migrar monolito para microserviços: o padrão Strangler Fig","Inicialize Tec",{"type":8,"value":9,"toc":1234},"minimark",[10,15,86,90,108,111,118,127,131,134,160,248,252,255,260,267,282,286,293,300,304,311,315,318,322,329,333,336,347,351,354,360,363,386,520,531,535,538,542,545,619,622,626,629,654,657,661,664,668,675,679,686,690,693,697,700,775,787,791,798,801,827,830,834,837,843,870,880,889,1002,1008,1017,1020,1024,1028,1035,1039,1042,1046,1052,1056,1059,1063,1066,1070,1139,1143,1216,1219,1230],[11,12,14],"h2",{"id":13},"índice","Índice",[16,17,18,26,32,38,44,50,56,62,68,74,80],"ol",{},[19,20,21],"li",{},[22,23,25],"a",{"href":24},"#o-que-e","O que é o padrão Strangler Fig",[19,27,28],{},[22,29,31],{"href":30},"#nao-reescreva","Por que \"reescrever tudo de uma vez\" dá errado",[19,33,34],{},[22,35,37],{"href":36},"#passo-a-passo","Como funciona, passo a passo",[19,39,40],{},[22,41,43],{"href":42},"#acl","O Anti-Corruption Layer (ACL)",[19,45,46],{},[22,47,49],{"href":48},"#roteamento","Roteamento: API Gateway e feature flags",[19,51,52],{},[22,53,55],{"href":54},"#banco","Migração de banco de dados",[19,57,58],{},[22,59,61],{"href":60},"#quando-parar","Quando parar de migrar",[19,63,64],{},[22,65,67],{"href":66},"#exemplo","Exemplo prático: extraindo o checkout",[19,69,70],{},[22,71,73],{"href":72},"#armadilhas","Anti-padrões e armadilhas reais",[19,75,76],{},[22,77,79],{"href":78},"#erros","Erros comuns",[19,81,82],{},[22,83,85],{"href":84},"#checklist","Checklist de migração",[11,87,89],{"id":88},"o-que-é-o-padrão-strangler-fig-o-que-e","O que é o padrão Strangler Fig {#o-que-e}",[91,92,93,94,98,99,102,103,107],"p",{},"O ",[95,96,97],"strong",{},"Strangler Fig"," é um padrão de migração incremental descrito por Martin\nFowler em 2004. O nome vem de uma árvore real, a ",[95,100,101],{},"figueira estranguladora","\n(",[104,105,106],"em",{},"strangler fig","), uma planta que cresce ao redor de outra árvore hospedeira.\nEla vai envolvendo o tronco aos poucos, ganhando espaço, até que um dia a\nárvore original morre e a figueira ocupa seu lugar — sem que em nenhum\nmomento a floresta ficou sem árvore.",[91,109,110],{},"A analogia no software é direta: em vez de derrubar o monolito (a árvore\nvelha) e plantar um sistema novo do zero, você vai envolvendo o monolito com\nserviços novos. Cada pedço de funcionalidade que sai do monolito vira um\nmicroserviço ao redor dele. O tráfego é desviado pouco a pouco para os\nserviços novos. Quando o monolito não tem mais nada útil dentro dele, você o\n\"desliga\" — e os microserviços já estão sustentando tudo sozinhos.",[91,112,113,114,117],{},"A ideia central é ",[95,115,116],{},"nunca parar de entregar valor"," durante a migração. O\nsistema continua no ar, os clientes continuam usando, o time continua\nlançando features. A migração acontece nas bordas, em pedaços pequenos e\nreversíveis.",[119,120,121],"blockquote",{},[91,122,123,126],{},[95,124,125],{},"Regra de ouro",": cada extração deve ser pequena o suficiente para ser\nrevertida em minutos se algo der errado. Se uma extração não pode ser\nrevertida, ela é grande demais.",[11,128,130],{"id":129},"por-que-reescrever-tudo-de-uma-vez-dá-errado-nao-reescreva","Por que \"reescrever tudo de uma vez\" dá errado {#nao-reescreva}",[91,132,133],{},"A tentação clássica é: \"nosso monolito está uma bagunça, vamos congelar as\nfeatures por 6 meses e reescrever tudo limpo\". Isso quase sempre termina\nmal. A história se repete:",[16,135,136,142,148,154],{},[19,137,138,141],{},[95,139,140],{},"O monolito continua evoluindo",": negócio não para. Enquanto o time novo\nreescreve, o monolito recebe features que a reescrita não conhece. No fim,\na reescrita está sempre atrás.",[19,143,144,147],{},[95,145,146],{},"Big bang deployment",": no dia de trocar, você descobre mil edge cases que\nsó existiam em produção. Sem rollback fácil, vira madrugada de incidente.",[19,149,150,153],{},[95,151,152],{},"Ninguém aprende com o monolito",": a reescrita repete erros que o monolito\njá tinha corrigido em produção há anos.",[19,155,156,159],{},[95,157,158],{},"ROI só no fim",": 6 meses sem entrega de valor, e só no dia D você sabe\nse funcionou. Risco enorme de ter gastado muito em algo que não atende.",[161,162,163,178],"table",{},[164,165,166],"thead",{},[167,168,169,173,176],"tr",{},[170,171,172],"th",{},"Abordagem",[170,174,175],{},"Reescrita big-bang",[170,177,97],{},[179,180,181,193,204,215,226,237],"tbody",{},[167,182,183,187,190],{},[184,185,186],"td",{},"Entrega de valor durante migração",[184,188,189],{},"Congelada",[184,191,192],{},"Contínua",[167,194,195,198,201],{},[184,196,197],{},"Risco por etapa",[184,199,200],{},"Muito alto",[184,202,203],{},"Baixo (reversível)",[167,205,206,209,212],{},[184,207,208],{},"Feedback do usuário",[184,210,211],{},"Só no fim",[184,213,214],{},"A cada extração",[167,216,217,220,223],{},[184,218,219],{},"Acompanha evolução do negócio",[184,221,222],{},"Não",[184,224,225],{},"Sim",[167,227,228,231,234],{},[184,229,230],{},"Tempo para primeiro microserviço em prod",[184,232,233],{},"Meses",[184,235,236],{},"Semanas",[167,238,239,242,245],{},[184,240,241],{},"Rollback",[184,243,244],{},"Quase impossível",[184,246,247],{},"Por extração",[11,249,251],{"id":250},"como-funciona-passo-a-passo-passo-a-passo","Como funciona, passo a passo {#passo-a-passo}",[91,253,254],{},"O fluxo do Strangler Fig é um ciclo que se repete para cada funcionalidade\nextraída:",[256,257,259],"h3",{"id":258},"passo-1-identificar-a-funcionalidade-candidata","Passo 1 — Identificar a funcionalidade candidata",[91,261,262,263,266],{},"Procure uma ",[95,264,265],{},"costura"," (seam) no monolito: uma parte com fronteiras razoavelmente\nclaras, baixo acoplamento com o resto e que traria valor sendo independente.\nBons candidatos:",[268,269,270,273,276,279],"ul",{},[19,271,272],{},"Funcionalidade com escala diferente do resto (ex.: busca vs. checkout).",[19,274,275],{},"Domínio que muda com frequência e trava deploys do monolito todo.",[19,277,278],{},"Integração com sistema externo que merece isolar.",[19,280,281],{},"Funcionalidade que um novo time vai assumir.",[256,283,285],{"id":284},"passo-2-colocar-um-interceptador-na-frente","Passo 2 — Colocar um \"interceptador\" na frente",[91,287,288,289,292],{},"Antes de mexer no monolito, coloque um ",[95,290,291],{},"ponto de roteamento"," entre clientes\ne o monolito. Pode ser um API Gateway, um proxy, ou até um pequeno\n\"facade\" dentro do próprio monolito. A função: redirecionar tráfego daquela\nfuncionalidade para onde você quiser, sem que o cliente perceba.",[91,294,295,296,299],{},"Neste momento, ",[95,297,298],{},"100% do tráfego ainda vai para o monolito",". Você só criou a\nalavanca de roteamento.",[256,301,303],{"id":302},"passo-3-construir-o-novo-microserviço","Passo 3 — Construir o novo microserviço",[91,305,306,307,310],{},"Construa o serviço novo, com seu próprio banco (ou réplica de leitura), sua\nprópria pipeline, seus próprios testes. Ele implementa ",[95,308,309],{},"só"," a funcionalidade\nescolhida.",[256,312,314],{"id":313},"passo-4-desviar-uma-fração-do-tráfego","Passo 4 — Desviar uma fração do tráfego",[91,316,317],{},"Roteie 1% (ou só um grupo interno, ou só um cliente piloto) para o novo serviço.\nCompare com o monolito: métricas, erros, latência, resultado de negócio. Se\nestiver igual ou melhor, aumente: 5% → 25% → 50% → 100%.",[256,319,321],{"id":320},"passo-5-remover-a-funcionalidade-do-monolito","Passo 5 — Remover a funcionalidade do monolito",[91,323,324,325,328],{},"Quando 100% do tráfego está no novo serviço, ",[95,326,327],{},"apague"," o código antigo do\nmonolito. Esse é o momento em que a figueira \"estrangulou\" aquele pedaço.\nA árvore velha ficou menor, o novo serviço ocupa aquele espaço.",[256,330,332],{"id":331},"passo-6-repetir","Passo 6 — Repetir",[91,334,335],{},"Volte ao Passo 1 com outra funcionalidade. O ciclo se repete até o monolito\nvirar uma casca vazia — ou até parar antes (veremos quando).",[337,338,343],"pre",{"className":339,"code":341,"language":342},[340],"language-text","           Cliente\n             │\n         [Gateway]\n        ╱   │   ╲       ← roteamento por funcionalidade\n       ╱    │    ╲\n  [MS-novo] [Monolito cada vez menor]\n","text",[344,345,341],"code",{"__ignoreMap":346},"",[11,348,350],{"id":349},"o-anti-corruption-layer-acl-acl","O Anti-Corruption Layer (ACL) {#acl}",[91,352,353],{},"Quando o novo microserviço precisa falar com o monolito (ou vice-versa), surge\num perigo silencioso: o modelo bagunçado do monolito \"vaza\" para o serviço\nnovo e o contamina. Você sai de um monolito sujo para microserviços sujos.",[91,355,93,356,359],{},[95,357,358],{},"Anti-Corruption Layer"," (camada anticorrupção) é uma tradução entre os\ndois mundos. Pense numa embaixada: você fala com o embaixador no seu idioma,\nele fala com o país estrangeiro no idioma deles. Você nunca precisa aprender\no idioma bagunçado do monolito, e o monolito nunca aprende o seu modelo limpo.",[91,361,362],{},"Na prática, o ACL é um pequeno componente (pode ser um serviço separado, um\nadapter, ou parte do gateway) que:",[268,364,365,372,383],{},[19,366,367,368,371],{},"Recebe chamadas no ",[95,369,370],{},"modelo novo"," (limpo, alinhado ao domínio).",[19,373,374,375,378,379,382],{},"Traduz para o ",[95,376,377],{},"modelo legado"," (tabelas espalhadas, campos ",[344,380,381],{},"campo_aux_2",",\nlógica escondida em triggers).",[19,384,385],{},"Esconde as idiossincrasias do monolito do resto do mundo novo.",[337,387,391],{"className":388,"code":389,"language":390,"meta":346,"style":346},"language-python shiki shiki-themes github-light github-dark","# ACL: traduz Pedido (modelo novo) para o formato que o monolito espera\n\nclass PedidoAcl:\n    def __init__(self, monolito_client):\n        self.monolito = monolito_client\n\n    def criar_pedido(self, pedido: Pedido) -> str:\n        # Modelo novo: limpo, legível\n        payload_legado = {\n            \"TBL_PEDIDO\": {\n                \"PED_ID_CLI\": pedido.cliente_id,         # campo renomeado\n                \"PED_VLR_TOT\": pedido.total,             # tipo ajustado\n                \"PED_DT_INC\": pedido.criado_em.strftime(\"%Y%m%d\"),  # formato antigo\n                \"PED_STA\": \"I\",                          # status inventado pelo legado\n            },\n            \"TBL_PEDIDO_AUX\": {\n                \"AUX_CAMPO2\": pedido.cupom or \"\",        # campo genérico reutilizado\n            },\n        }\n        resposta = self.monolito.gravar(payload_legado)\n        return resposta[\"PED_ID\"]\n","python",[344,392,393,401,408,414,420,426,431,437,443,449,455,461,467,473,479,485,491,497,502,508,514],{"__ignoreMap":346},[394,395,398],"span",{"class":396,"line":397},"line",1,[394,399,400],{},"# ACL: traduz Pedido (modelo novo) para o formato que o monolito espera\n",[394,402,404],{"class":396,"line":403},2,[394,405,407],{"emptyLinePlaceholder":406},true,"\n",[394,409,411],{"class":396,"line":410},3,[394,412,413],{},"class PedidoAcl:\n",[394,415,417],{"class":396,"line":416},4,[394,418,419],{},"    def __init__(self, monolito_client):\n",[394,421,423],{"class":396,"line":422},5,[394,424,425],{},"        self.monolito = monolito_client\n",[394,427,429],{"class":396,"line":428},6,[394,430,407],{"emptyLinePlaceholder":406},[394,432,434],{"class":396,"line":433},7,[394,435,436],{},"    def criar_pedido(self, pedido: Pedido) -> str:\n",[394,438,440],{"class":396,"line":439},8,[394,441,442],{},"        # Modelo novo: limpo, legível\n",[394,444,446],{"class":396,"line":445},9,[394,447,448],{},"        payload_legado = {\n",[394,450,452],{"class":396,"line":451},10,[394,453,454],{},"            \"TBL_PEDIDO\": {\n",[394,456,458],{"class":396,"line":457},11,[394,459,460],{},"                \"PED_ID_CLI\": pedido.cliente_id,         # campo renomeado\n",[394,462,464],{"class":396,"line":463},12,[394,465,466],{},"                \"PED_VLR_TOT\": pedido.total,             # tipo ajustado\n",[394,468,470],{"class":396,"line":469},13,[394,471,472],{},"                \"PED_DT_INC\": pedido.criado_em.strftime(\"%Y%m%d\"),  # formato antigo\n",[394,474,476],{"class":396,"line":475},14,[394,477,478],{},"                \"PED_STA\": \"I\",                          # status inventado pelo legado\n",[394,480,482],{"class":396,"line":481},15,[394,483,484],{},"            },\n",[394,486,488],{"class":396,"line":487},16,[394,489,490],{},"            \"TBL_PEDIDO_AUX\": {\n",[394,492,494],{"class":396,"line":493},17,[394,495,496],{},"                \"AUX_CAMPO2\": pedido.cupom or \"\",        # campo genérico reutilizado\n",[394,498,500],{"class":396,"line":499},18,[394,501,484],{},[394,503,505],{"class":396,"line":504},19,[394,506,507],{},"        }\n",[394,509,511],{"class":396,"line":510},20,[394,512,513],{},"        resposta = self.monolito.gravar(payload_legado)\n",[394,515,517],{"class":396,"line":516},21,[394,518,519],{},"        return resposta[\"PED_ID\"]\n",[91,521,522,523,526,527,530],{},"Sem o ACL, o ",[344,524,525],{},"cupom"," viraria ",[344,528,529],{},"AUX_CAMPO2"," espalhado por todo o serviço novo —\na bagunça teria migrado. Com o ACL, a sujeira fica num lugar só, fácil de\njogar fora quando o monolito morrer.",[11,532,534],{"id":533},"roteamento-api-gateway-e-feature-flags-roteamento","Roteamento: API Gateway e feature flags {#roteamento}",[91,536,537],{},"O roteamento é o coração operacional do Strangler Fig. As duas ferramentas\nmais usadas:",[256,539,541],{"id":540},"api-gateway","API Gateway",[91,543,544],{},"Um gateway (Kong, Traefik, AWS API Gateway, Envoy) recebe todas as requisições\ne decide, por path, para onde mandar:",[337,546,550],{"className":547,"code":548,"language":549,"meta":346,"style":346},"language-yaml shiki shiki-themes github-light github-dark","# Exemplo conceitual de rotas no gateway\nroutes:\n  - path: \u002Fapi\u002Fcheckout\u002F*        # extraído → vai para o novo serviço\n    upstream: checkout-service\n  - path: \u002Fapi\u002F*                 # resto → continua no monolito\n    upstream: monolito\n","yaml",[344,551,552,558,568,586,596,610],{"__ignoreMap":346},[394,553,554],{"class":396,"line":397},[394,555,557],{"class":556},"sJ8bj","# Exemplo conceitual de rotas no gateway\n",[394,559,560,564],{"class":396,"line":403},[394,561,563],{"class":562},"s9eBZ","routes",[394,565,567],{"class":566},"sVt8B",":\n",[394,569,570,573,576,579,583],{"class":396,"line":410},[394,571,572],{"class":566},"  - ",[394,574,575],{"class":562},"path",[394,577,578],{"class":566},": ",[394,580,582],{"class":581},"sZZnC","\u002Fapi\u002Fcheckout\u002F*",[394,584,585],{"class":556},"        # extraído → vai para o novo serviço\n",[394,587,588,591,593],{"class":396,"line":416},[394,589,590],{"class":562},"    upstream",[394,592,578],{"class":566},[394,594,595],{"class":581},"checkout-service\n",[394,597,598,600,602,604,607],{"class":396,"line":422},[394,599,572],{"class":566},[394,601,575],{"class":562},[394,603,578],{"class":566},[394,605,606],{"class":581},"\u002Fapi\u002F*",[394,608,609],{"class":556},"                 # resto → continua no monolito\n",[394,611,612,614,616],{"class":396,"line":428},[394,613,590],{"class":562},[394,615,578],{"class":566},[394,617,618],{"class":581},"monolito\n",[91,620,621],{},"Vantagem: roteamento centralizado, fácil de mudar, sem mexer no código do\nmonolito. Quando a extração terminar, só remove a rota legada.",[256,623,625],{"id":624},"feature-flags-para-migração-interna","Feature flags para migração interna",[91,627,628],{},"Para funcionalidades dentro do mesmo backend, use feature flags (LaunchDarkly,\nUnleash, Flagsmith) para decidir por usuário\u002Ftenant se a chamada usa o código\nantigo ou o novo serviço:",[337,630,632],{"className":388,"code":631,"language":390,"meta":346,"style":346},"def processar_pagamento(pedido):\n    if feature_flag.usar_servico_novo(pedido.cliente_id):\n        return pagamento_service_novo.cobrar(pedido)   # microserviço\n    return gateway_monolito.cobrar(pedido)              # legado\n",[344,633,634,639,644,649],{"__ignoreMap":346},[394,635,636],{"class":396,"line":397},[394,637,638],{},"def processar_pagamento(pedido):\n",[394,640,641],{"class":396,"line":403},[394,642,643],{},"    if feature_flag.usar_servico_novo(pedido.cliente_id):\n",[394,645,646],{"class":396,"line":410},[394,647,648],{},"        return pagamento_service_novo.cobrar(pedido)   # microserviço\n",[394,650,651],{"class":396,"line":416},[394,652,653],{},"    return gateway_monolito.cobrar(pedido)              # legado\n",[91,655,656],{},"Assim você libera o novo serviço primeiro para clientes beta, compara\ncomportamento e expande sem deploys arriscados.",[11,658,660],{"id":659},"migração-de-banco-de-dados-banco","Migração de banco de dados {#banco}",[91,662,663],{},"O banco é geralmente a parte mais difícil da migração. O monolito costuma ter\num banco gigante e compartilhado, e os dados não se separam em domínios tão\nfacilmente quanto o código. Estratégias, do mais simples ao mais avançado:",[256,665,667],{"id":666},"_1-banco-compartilhado-não-recomendado-mas-realista","1. Banco compartilhado (não recomendado, mas realista)",[91,669,670,671,674],{},"O novo serviço acessa o mesmo banco do monolito, com permissão só de leitura\nem tabelas que precisa. Rápido para começar, mas ",[95,672,673],{},"quebra o isolamento"," —\nmudança de schema do monolito quebra o serviço novo. Use só como passo\ntemporário.",[256,676,678],{"id":677},"_2-réplica-de-leitura-via-cdc","2. Réplica de leitura via CDC",[91,680,681,682,685],{},"Use ",[95,683,684],{},"CDC"," (Change Data Capture — captura de mudanças de dados) com\nDebezium para replicar as tabelas relevantes do monolito para o banco do\nnovo serviço. O serviço lê do seu próprio banco (rápido), e os dados se\natualizam em segundos via stream de mudanças. Mantém isolamento sem mudar o\nmonolito.",[256,687,689],{"id":688},"_3-sincronização-por-eventos","3. Sincronização por eventos",[91,691,692],{},"O monolito publica eventos (\"pedido criado\", \"cliente atualizado\") num broker\n(Kafka) e o novo serviço consome e monta sua própria visão dos dados. É o\nmodelo mais limpo, mas exige que o monolito aprenda a publicar eventos —\nmodificação necessária.",[256,694,696],{"id":695},"_4-separação-completa-estado-final","4. Separação completa (estado final)",[91,698,699],{},"O novo serviço é dono dos seus dados. O monolito deixa de escrever naquelas\ntabelas. Migração dos registros existentes feita em batch. Esta é a chegada\ndo \"serviço realmente independente\".",[161,701,702,718],{},[164,703,704],{},[167,705,706,709,712,715],{},[170,707,708],{},"Estratégia",[170,710,711],{},"Esforço inicial",[170,713,714],{},"Isolamento",[170,716,717],{},"Quando usar",[179,719,720,734,748,762],{},[167,721,722,725,728,731],{},[184,723,724],{},"Banco compartilhado",[184,726,727],{},"Baixo",[184,729,730],{},"Nenhum",[184,732,733],{},"Primeira extração, ponte rápida",[167,735,736,739,742,745],{},[184,737,738],{},"Réplica via CDC",[184,740,741],{},"Médio",[184,743,744],{},"Alto (leitura)",[184,746,747],{},"Serviço só lê dados do monolito",[167,749,750,753,756,759],{},[184,751,752],{},"Sincronização por eventos",[184,754,755],{},"Médio-alto",[184,757,758],{},"Alto",[184,760,761],{},"Serviço precisa reagir a mudanças",[167,763,764,767,769,772],{},[184,765,766],{},"Separação completa",[184,768,758],{},[184,770,771],{},"Total",[184,773,774],{},"Estado final, dono dos dados",[119,776,777],{},[91,778,779,782,783,786],{},[95,780,781],{},"Cuidado com joins cross-serviço",": quando os dados estão em bancos\ndiferentes, um ",[344,784,785],{},"JOIN"," trivial vira uma dor. Planeje agregações via\nmaterialized views, desnormalização ou chamadas de API com cache.",[11,788,790],{"id":789},"quando-parar-de-migrar-quando-parar","Quando parar de migrar {#quando-parar}",[91,792,793,794,797],{},"Um erro comum é achar que o objetivo é \"extrair tudo\". Não é. O objetivo é\n",[95,795,796],{},"entregar valor",", e às vezes parar no meio é a decisão certa.",[91,799,800],{},"Pare de extrair quando:",[268,802,803,809,815,821],{},[19,804,805,808],{},[95,806,807],{},"O que sobrou no monolito é estável e baixo risco",": funcionalidades que\nnão mudam há anos, com escala sem pressão, podem ficar no monolito para\nsempre. Um monolito pequeno e estável é ótimo.",[19,810,811,814],{},[95,812,813],{},"O custo da próxima extração supera o benefício",": as últimas costuras são\nas mais difíceis (alto acoplamento). Se a extração custa 3 meses e libera\npouco valor, mantenha no monolito.",[19,816,817,820],{},[95,818,819],{},"A equipe precisa entregar features",": prioridade de negócio mudou. Pausar\na migração não é fracasso, é pragmatismo.",[19,822,823,826],{},[95,824,825],{},"O monolito virou \"serviço CRUD\":"," quando só sobram telas simples e\nCRUDs, ele é praticamente um microserviço grande. Deixe quieto.",[91,828,829],{},"O Strangler Fig não é uma religião. É uma ferramenta. Use enquanto pagar.",[11,831,833],{"id":832},"exemplo-prático-extraindo-o-checkout-exemplo","Exemplo prático: extraindo o checkout {#exemplo}",[91,835,836],{},"Cenário: e-commerce com monolito em Rails. Checkout é o gargalo de escala\n(black friday) e trava deploys. Vamos extraí-lo.",[91,838,839,842],{},[95,840,841],{},"Semana 1 — Roteamento","\nColocamos um API Gateway na frente do monolito. Tudo ainda aponta para o\nmonolito. Métricas de baseline coletadas (latência, erro rate por path).",[91,844,845,848,849,852,853,852,856,859,860,852,863,852,866,869],{},[95,846,847],{},"Semana 2-3 — Modelo e ACL","\nDefinimos o modelo ",[344,850,851],{},"Pedido",", ",[344,854,855],{},"Item",[344,857,858],{},"Pagamento"," do novo serviço. Criamos a\nACL que traduz para as tabelas ",[344,861,862],{},"pedidos",[344,864,865],{},"itens_ped",[344,867,868],{},"pgto"," do monolito.",[91,871,872,875,876,879],{},[95,873,874],{},"Semana 4-6 — Novo serviço","\nConstruímos ",[344,877,878],{},"checkout-service"," em Go, com seu próprio banco (Postgres). Usa\nCDC do monolito para ter o catálogo de produtos e preços (réplica de leitura).",[91,881,882,885,886,888],{},[95,883,884],{},"Semana 7 — Canary","\nGateway roteia ",[344,887,582],{}," para o novo serviço em 1% do tráfego\n(clientes marcados como beta). Comparação lado a lado:",[337,890,892],{"className":547,"code":891,"language":549,"meta":346,"style":346},"# Config de canary no gateway\nroutes:\n  - path: \u002Fapi\u002Fcheckout\u002F*\n    strategy: canary\n    canary:\n      upstream: checkout-service\n      weight: 1        # 1% para o novo\n      fallback: monolito\n    monitor:\n      error_rate_threshold: 0.5%\n      latency_p99_threshold: 800ms\n      auto_rollback: true\n",[344,893,894,899,905,916,926,933,942,956,965,972,982,992],{"__ignoreMap":346},[394,895,896],{"class":396,"line":397},[394,897,898],{"class":556},"# Config de canary no gateway\n",[394,900,901,903],{"class":396,"line":403},[394,902,563],{"class":562},[394,904,567],{"class":566},[394,906,907,909,911,913],{"class":396,"line":410},[394,908,572],{"class":566},[394,910,575],{"class":562},[394,912,578],{"class":566},[394,914,915],{"class":581},"\u002Fapi\u002Fcheckout\u002F*\n",[394,917,918,921,923],{"class":396,"line":416},[394,919,920],{"class":562},"    strategy",[394,922,578],{"class":566},[394,924,925],{"class":581},"canary\n",[394,927,928,931],{"class":396,"line":422},[394,929,930],{"class":562},"    canary",[394,932,567],{"class":566},[394,934,935,938,940],{"class":396,"line":428},[394,936,937],{"class":562},"      upstream",[394,939,578],{"class":566},[394,941,595],{"class":581},[394,943,944,947,949,953],{"class":396,"line":433},[394,945,946],{"class":562},"      weight",[394,948,578],{"class":566},[394,950,952],{"class":951},"sj4cs","1",[394,954,955],{"class":556},"        # 1% para o novo\n",[394,957,958,961,963],{"class":396,"line":439},[394,959,960],{"class":562},"      fallback",[394,962,578],{"class":566},[394,964,618],{"class":581},[394,966,967,970],{"class":396,"line":445},[394,968,969],{"class":562},"    monitor",[394,971,567],{"class":566},[394,973,974,977,979],{"class":396,"line":451},[394,975,976],{"class":562},"      error_rate_threshold",[394,978,578],{"class":566},[394,980,981],{"class":581},"0.5%\n",[394,983,984,987,989],{"class":396,"line":457},[394,985,986],{"class":562},"      latency_p99_threshold",[394,988,578],{"class":566},[394,990,991],{"class":581},"800ms\n",[394,993,994,997,999],{"class":396,"line":463},[394,995,996],{"class":562},"      auto_rollback",[394,998,578],{"class":566},[394,1000,1001],{"class":951},"true\n",[91,1003,1004,1007],{},[95,1005,1006],{},"Semana 8-10 — Expansão","\nSem incidentes, subimos para 10% → 50% → 100%. Em 100%, o monolito para de\nreceber checkout.",[91,1009,1010,1013,1014,1016],{},[95,1011,1012],{},"Semana 11 — Limpeza","\nRemovemos o código de checkout do monolito. Apagamos as rotas legadas. O\nmonolito encolheu. O ",[344,1015,878],{}," deploya sozinho, escala sozinho, e\nestá pronto para a próxima black friday.",[91,1018,1019],{},"Total: ~11 semanas, com valor entregue em produção desde a semana 7, e\nreversível a qualquer momento até a semana 10.",[11,1021,1023],{"id":1022},"anti-padrões-e-armadilhas-reais-armadilhas","Anti-padrões e armadilhas reais {#armadilhas}",[256,1025,1027],{"id":1026},"distribuído-demais","\"Distribuído demais\"",[91,1029,1030,1031,1034],{},"Cada extração cria um novo serviço, novo banco, nova pipeline. Extrair 40\nserviços de um monolito de 5 pessoas gera mais dor do que valor. ",[95,1032,1033],{},"A extração\ndeve seguir fronteiras de domínio e de time",", não fronteiras de classe.",[256,1036,1038],{"id":1037},"banho-de-dados-compartilhado-disfarçado","\"Banho de dados compartilhado disfarçado\"",[91,1040,1041],{},"Serviços \"separados\" que compartilham o mesmo banco não são microserviços —\nsão um monolito distribuído com latência de rede. O isolamento de dados é o\nque define o limite real.",[256,1043,1045],{"id":1044},"síndrome-do-bolso-cheio-de-features","\"Síndrome do bolso-cheio de features\"",[91,1047,1048,1049],{},"Aproveitar a migração para \"reformar\" a funcionalidade — adicionar features\nnovas, mudar regras de negócio, redesenhar UX. Isso quebra a comparabilidade\nentre o novo e o velho, dificultando o canary e o rollback. ",[95,1050,1051],{},"Primeiro migre\ncomportamento igual. Só depois evolua.",[256,1053,1055],{"id":1054},"sem-observabilidade-no-novo-serviço","\"Sem observabilidade no novo serviço\"",[91,1057,1058],{},"Colocar um serviço novo em produção sem tracing distribuído, métricas RED e\nlogs estruturados é dirigir no escuro. Você não consegue comparar com o\nmonolito, não detecta regressões, e o canary vira loteria.",[256,1060,1062],{"id":1061},"dependência-circular-nova-velho-nova","\"Dependência circular nova → velho → nova\"",[91,1064,1065],{},"O serviço novo chama o monolito, que chama o serviço novo. Latência explode\ne debugging vira pesadelo. Quebre o ciclo: evento assíncrono, ou consolide\na responsabilidade num único lado.",[11,1067,1069],{"id":1068},"erros-comuns-erros","Erros comuns {#erros}",[16,1071,1072,1078,1088,1094,1100,1106,1115,1121,1127,1133],{},[19,1073,1074,1077],{},[95,1075,1076],{},"Reescrever em vez de estrangular",": parar o time por meses. Estrangule\nincrementalmente e entregue valor desde cedo.",[19,1079,1080,1083,1084,1087],{},[95,1081,1082],{},"Sem gateway\u002Fproxy antes de começar",": quando você precisa desviar\ntráfego, descobre que o cliente chama o monolito direto por IP. Coloque o\nroteamento ",[95,1085,1086],{},"antes"," de extrair qualquer coisa.",[19,1089,1090,1093],{},[95,1091,1092],{},"Extração grande e irreversível",": a primeira extração deve ser pequena e\nreversível para treinar o processo. Pegue uma funcionalidade de baixo risco\nprimeiro.",[19,1095,1096,1099],{},[95,1097,1098],{},"Ignorar o ACL",": o modelo sujo do monolito contamina o serviço novo.\nTraduça sempre numa camada isolada.",[19,1101,1102,1105],{},[95,1103,1104],{},"Misturar migração com evolução",": mudar regras durante a migração\nquebra o canary. Mantenha o comportamento idêntico até 100%.",[19,1107,1108,1111,1112,1114],{},[95,1109,1110],{},"Sem estratégia de dados",": começar o serviço novo sem definir se vai\ncompartilhar, replicar ou sincronizar dados. Decida o modelo de dados\n",[95,1113,1086],{}," de escrever a primeira linha do serviço.",[19,1116,1117,1120],{},[95,1118,1119],{},"Não comparar métricas novo vs. velho",": rodar canary sem dashboard lado\na lado. Você só descobre o problema quando o cliente reclama.",[19,1122,1123,1126],{},[95,1124,1125],{},"Não remover o código velho",": depois de 100% no novo, o código legado\nfica \"por via das dúvidas\". Vira dívida que ninguém entende mais. Remova.",[19,1128,1129,1132],{},[95,1130,1131],{},"Extrair sem fronteira de time",": um microserviço que ninguém é dono vira\nórfão. Só extraia se houver um time para assumi-lo.",[19,1134,1135,1138],{},[95,1136,1137],{},"Achar que Strangler Fig é para tudo",": algumas partes do monolito podem\ne devem ficar. Avalie custo\u002Fbenefício de cada extração.",[11,1140,1142],{"id":1141},"checklist-de-migração-checklist","Checklist de migração {#checklist}",[268,1144,1147,1156,1162,1168,1174,1180,1186,1192,1198,1204,1210],{"className":1145},[1146],"contains-task-list",[19,1148,1151,1155],{"className":1149},[1150],"task-list-item",[1152,1153],"input",{"disabled":406,"type":1154},"checkbox"," Gateway\u002Fproxy na frente do monolito antes de qualquer extração",[19,1157,1159,1161],{"className":1158},[1150],[1152,1160],{"disabled":406,"type":1154}," Funcionalidade candidata tem fronteira de domínio e de time clara",[19,1163,1165,1167],{"className":1164},[1150],[1152,1166],{"disabled":406,"type":1154}," ACL definida para traduzir modelo novo ↔ legado",[19,1169,1171,1173],{"className":1170},[1150],[1152,1172],{"disabled":406,"type":1154}," Estratégia de dados escolhida (compartilhado, CDC, eventos, separação)",[19,1175,1177,1179],{"className":1176},[1150],[1152,1178],{"disabled":406,"type":1154}," Novo serviço com observabilidade (logs, métricas RED, tracing)",[19,1181,1183,1185],{"className":1182},[1150],[1152,1184],{"disabled":406,"type":1154}," Pipeline de CI\u002FCD independente para o novo serviço",[19,1187,1189,1191],{"className":1188},[1150],[1152,1190],{"disabled":406,"type":1154}," Canary com comparação de métricas lado a lado e auto-rollback",[19,1193,1195,1197],{"className":1194},[1150],[1152,1196],{"disabled":406,"type":1154}," Comportamento idêntico ao legado durante a migração (sem features novas)",[19,1199,1201,1203],{"className":1200},[1150],[1152,1202],{"disabled":406,"type":1154}," Plano de remoção do código velho ao atingir 100%",[19,1205,1207,1209],{"className":1206},[1150],[1152,1208],{"disabled":406,"type":1154}," Documentação da decisão de parar (se parar antes do fim)",[19,1211,1213,1215],{"className":1212},[1150],[1152,1214],{"disabled":406,"type":1154}," Reversibilidade testada: simular rollback e medir tempo de recuperação",[1217,1218],"hr",{},[91,1220,1221,1224,1225,1229],{},[95,1222,1223],{},"Migrando do monolito para microserviços?"," A Inicialize Tec conduz migrações\nincrementais com Strangler Fig — da escolha das primeiras costuras ao\nroteamento, ACL e estratégia de dados, sem parar suas entregas.\n",[22,1226,1228],{"href":1227},"\u002F#top","Conversamos sobre seu caso",".",[1231,1232,1233],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":346,"searchDepth":410,"depth":410,"links":1235},[1236,1237,1238,1239,1247,1248,1252,1258,1259,1260,1267,1268],{"id":13,"depth":403,"text":14},{"id":88,"depth":403,"text":89},{"id":129,"depth":403,"text":130},{"id":250,"depth":403,"text":251,"children":1240},[1241,1242,1243,1244,1245,1246],{"id":258,"depth":410,"text":259},{"id":284,"depth":410,"text":285},{"id":302,"depth":410,"text":303},{"id":313,"depth":410,"text":314},{"id":320,"depth":410,"text":321},{"id":331,"depth":410,"text":332},{"id":349,"depth":403,"text":350},{"id":533,"depth":403,"text":534,"children":1249},[1250,1251],{"id":540,"depth":410,"text":541},{"id":624,"depth":410,"text":625},{"id":659,"depth":403,"text":660,"children":1253},[1254,1255,1256,1257],{"id":666,"depth":410,"text":667},{"id":677,"depth":410,"text":678},{"id":688,"depth":410,"text":689},{"id":695,"depth":410,"text":696},{"id":789,"depth":403,"text":790},{"id":832,"depth":403,"text":833},{"id":1022,"depth":403,"text":1023,"children":1261},[1262,1263,1264,1265,1266],{"id":1026,"depth":410,"text":1027},{"id":1037,"depth":410,"text":1038},{"id":1044,"depth":410,"text":1045},{"id":1054,"depth":410,"text":1055},{"id":1061,"depth":410,"text":1062},{"id":1068,"depth":403,"text":1069},{"id":1141,"depth":403,"text":1142},"sistemas-escalaveis","2026-08-26","Como migrar uma aplicação monolítica para microserviços sem parar o time: o padrão Strangler Fig, anti-corruption layer e armadilhas reais.","md",[1274,1275,1276,106,1277,1278],"monolito","microserviços","migração","refatoração","arquitetura",{},"\u002Fsistemas\u002Fmigrar-monolito-para-microservicos",{"title":5,"description":1271},"migrar-monolito-para-microservicos","sistemas\u002Fmigrar-monolito-para-microservicos","GfahoUqOsk91r2Kqw-8HX5fMb3sPEBDjEaJBycm4MHI",1787796309706]