Módulo 3: El patrón strangler fig
Proyecto: poner el catalog de Mercado detrás de un strangler facade
Descripción
Llegaste al capstone del módulo. En las siete lecciones anteriores construiste el patrón strangler fig pieza por pieza: el facade transparente (L2), el servicio nuevo al lado (L3), el desvío por porcentaje con fallback (L4), las tres estrategias de desvío (L5), la observabilidad y el gate de promoción (L6), y el corte final con burn-down y retiro (L7). En este proyecto juntas todo en una sola simulación ejecutada: modernizas el catalog de Mercado de punta a punta, con un StranglerFacade que integra las cuatro fases, corrido como un diario de migración día por día.
El diario es la forma más honesta de ver un strangler completo, porque muestra lo que las lecciones aisladas no: cómo las piezas trabajan juntas a lo largo del tiempo. Vas a ver el gate subir el traffic_percent solo cuando la ruta nueva está sana, un bug que aparece a mitad del ramp y frena la promoción, el equipo que despliega el arreglo, el ramp que se reanuda, el burn-down que llega a cero, y —el premio— el legacy que se retira. Es la película entera, no las fotos sueltas.
Y este proyecto tiene una entrega, como todo capstone: (1) el plan de migración por rebanadas —por qué el catálogo, y en qué orden lo demás—, (2) el código ejecutado —el StranglerFacade completo corrido con su salida literal—, y (3) la justificación de por qué este camino incremental venció al rewrite que el módulo 1 desmontó. Al terminar, tendrás en las manos una migración de una rebanada real, de principio a fin, que puedes defender con números.
Conexión con el módulo. Este proyecto integra las lecciones 2 a 7 en una ejecución continua. Cierra el módulo 3 y prepara los dos que siguen: el módulo 4 (branch by abstraction) enseña la variante para cuando no hay una frontera externa donde poner el facade —la migración por dentro del código—; y el módulo 5 (extraer un servicio) toma el modern que aquí construimos al lado y lo saca a su propio proceso con un anti-corruption layer. Fíjate en la frontera del capstone: aquí modernizamos el catalog con la técnica del strangler (desvío de tráfico externo). Cómo está construido el modern por dentro y a dónde termina (microservicio, eventos) es de las guías de estilos; migrar sus datos sin downtime es el módulo 6; y medir el progreso de la migración completa de Mercado (todas las rebanadas) es el módulo 7. Este capstone es una rebanada, ejecutada entera.
El plan de migración por rebanadas
Antes del código, el plan —porque un strangler sin plan es solo un proxy—. Mercado es un monolito con cuatro módulos: catalog, orders, payments, shipping. No los migramos todos a la vez; elegimos una primera rebanada y la llevamos de punta a punta antes de tocar la siguiente. El módulo 1 ya hizo esta elección (el catálogo: alto valor, bajo acoplamiento, buen candidato); aquí la ejecutamos.
Rebanada Por que en este orden Estado en este proyecto
────────── ───────────────────────────────────────────── ──────────────────────
catalog alto valor, bajo acoplamiento (poco escribe; <- ESTA rebanada,
lee mucho); riesgo bajo si el canary falla de punta a punta
orders depende del catalog; se migra despues siguiente
payments critico (dinero); se migra con mas cuidado mas adelante
shipping acoplado a orders; ultimo ultimo
El principio del plan por rebanadas: una rebanada a la vez, de punta a punta. No abras el strangler de orders mientras el de catalog está a medias —terminarías con cuatro migraciones al 40%, ninguna cobrada—. Llevas el catalog hasta retirar su legacy, cobras el premio (una rebanada menos de monolito), y entonces empiezas orders. Cada rebanada completa reduce el monolito y te enseña algo para la siguiente.
Una analogía: mudarte de casa cuarto por cuarto, terminando cada uno
Piensa en mudar todo tu hogar de una casa vieja a una nueva, pero con la regla de que nunca puedes quedarte sin un cuarto funcional. No cargas todo en un camión un día (eso es el big-bang). Mudas un cuarto a la vez, y lo terminas antes de empezar el siguiente: primero la cocina —la montas completa en la casa nueva, la usas unos días, confirmas que todo funciona (el agua, el gas, los electrodomésticos)—, y solo cuando la cocina nueva funciona del todo, vacías y desmantelas la cocina vieja. Recién entonces empiezas con la recámara.
Si mudaras los cuatro cuartos "un poco cada uno" a la vez, vivirías semanas con cuatro cuartos a medio armar, ninguno usable, cajas por todos lados. Terminar cada cuarto antes de empezar el siguiente te da, en cada paso, un cuarto completamente funcional en la casa nueva y un cuarto completamente vacío en la vieja —progreso real y cobrado—.
La casa vieja es el monolito; los cuartos son las rebanadas (catalog, orders...). Montar la cocina nueva y usarla unos días antes de desmantelar la vieja es el ramp del strangler con su burn-down. Y desmantelar la cocina vieja cuando la nueva funciona es retirar el legacy. Este proyecto muda la cocina —el catalog— completa, de punta a punta.
Ejemplo trabajado: el diario de migración del catalog, ejecutado
Aquí está el StranglerFacade completo, integrando las cuatro fases del módulo, corrido como un diario día por día. El facade enruta por porcentaje con fallback (L4), observa las dos rutas y calcula el error_rate (L6), y un gate sube el traffic_percent por el ramp solo cuando la ruta nueva está sana. El modern arranca con el bug de webcam (v1) y el equipo despliega el arreglo (v2) el día 3. Cuando el ramp llega a 100% y el burn-down toca cero (fallback 0), el legacy se retira (L7).
# ============================================================================
# Capstone: modernizar el catalog de Mercado con un strangler facade,
# de punta a punta y EJECUTADO. Facade + servicio nuevo al lado + desvio por
# porcentaje con fallback + observabilidad + gate + burn-down + retiro.
# ============================================================================
import zlib
def legacy_catalog(request):
return {"source": "legacy", "product": request["q"]}
def modern_catalog(request, version):
# v1 falla en "webcam" (out-of-stock no implementado); v2 lo arregla.
if version == 1 and request["q"] == "webcam":
raise ValueError("modern v1: unhandled out-of-stock path")
return {"source": "modern", "product": request["q"]}
def bucket(request_id):
return zlib.crc32(str(request_id).encode()) % 100
class StranglerFacade:
def __init__(self):
self.traffic_percent = 0
self.modern_version = 1 # arranca con el bug
self.retired = False
def handle_batch(self, requests):
obs = {"modern_ok": 0, "fallback": 0, "legacy": 0}
for req in requests:
goes_modern = (not self.retired) and bucket(req["id"]) < self.traffic_percent
if self.retired:
goes_modern = True # ya no hay legacy: todo va a modern
if goes_modern:
try:
modern_catalog(req, self.modern_version)
obs["modern_ok"] += 1
except Exception:
obs["fallback"] += 1
legacy_catalog(req) # la vieja ruta es la red de seguridad
else:
legacy_catalog(req)
obs["legacy"] += 1
return obs
def error_rate(obs):
attempted = obs["modern_ok"] + obs["fallback"]
return (obs["fallback"] / attempted * 100) if attempted else 0.0
def pct_on_new_route(obs):
total = obs["modern_ok"] + obs["fallback"] + obs["legacy"]
return obs["modern_ok"] / total * 100 if total else 0.0
# --- Trafico fijo del catalog: 1 de cada 10 consulta "webcam". ---
N = 1000
requests = [{"id": i, "q": "webcam" if i % 10 == 0 else "ssd"} for i in range(1, N + 1)]
RAMP = [0, 10, 25, 50, 75, 100]
GATE = 1.0 # promover solo si error_rate de la ruta nueva <= 1%
facade = StranglerFacade()
ramp_idx = 0
FIX_DAY = 3 # el equipo despliega modern v2 (arreglado) este dia
print("Diario de migracion del catalog de Mercado (gate = error_rate <= 1.0%)\n")
print(f"{'dia':>4}{'traffic':>9}{'ver':>5}{'ok':>6}{'fb':>5}{'legacy':>8}"
f"{'err%':>7}{'new%':>7} decision")
print("-" * 74)
for day in range(1, 9):
if day == FIX_DAY:
facade.modern_version = 2 # se arregla el bug de webcam
used_pct = facade.traffic_percent # el % con el que corre ESTE dia
obs = facade.handle_batch(requests)
er = error_rate(obs)
newp = pct_on_new_route(obs)
# Gate: si la ruta nueva esta sana, sube al siguiente escalon del ramp.
decision = "-"
if facade.retired:
decision = "legacy RETIRADO"
elif facade.traffic_percent == 100 and obs["fallback"] == 0:
facade.retired = True
decision = "burn-down=0 -> RETIRAR legacy"
elif er <= GATE and ramp_idx < len(RAMP) - 1:
ramp_idx += 1
facade.traffic_percent = RAMP[ramp_idx]
decision = f"gate OK -> subir a {RAMP[ramp_idx]}%"
elif er > GATE:
decision = "gate FALLA -> HOLD (arreglar)"
print(f"{day:>4}{used_pct:>8}%{facade.modern_version:>5}"
f"{obs['modern_ok']:>6}{obs['fallback']:>5}{obs['legacy']:>8}"
f"{er:>6.1f}%{newp:>6.1f}% {decision}")
print("-" * 74)
print("\nEntregable: el catalog de Mercado quedo 100% en el servicio nuevo,")
print("el legacy se retiro (0 llamadas), y cada escalon se subio solo cuando")
print("la ruta nueva estuvo sana. Incremental, medido y reversible en cada paso.")
Qué esperar. Al correr el archivo, la salida es exactamente esta:
Diario de migracion del catalog de Mercado (gate = error_rate <= 1.0%)
dia traffic ver ok fb legacy err% new% decision
--------------------------------------------------------------------------
1 0% 1 0 0 1000 0.0% 0.0% gate OK -> subir a 10%
2 10% 1 99 10 891 9.2% 9.9% gate FALLA -> HOLD (arreglar)
3 10% 2 109 0 891 0.0% 10.9% gate OK -> subir a 25%
4 25% 2 271 0 729 0.0% 27.1% gate OK -> subir a 50%
5 50% 2 520 0 480 0.0% 52.0% gate OK -> subir a 75%
6 75% 2 765 0 235 0.0% 76.5% gate OK -> subir a 100%
7 100% 2 1000 0 0 0.0% 100.0% burn-down=0 -> RETIRAR legacy
8 100% 2 1000 0 0 0.0% 100.0% legacy RETIRADO
--------------------------------------------------------------------------
Entregable: el catalog de Mercado quedo 100% en el servicio nuevo,
el legacy se retiro (0 llamadas), y cada escalon se subio solo cuando
la ruta nueva estuvo sana. Incremental, medido y reversible en cada paso.
Lee el diario día por día, porque cada renglón es una decisión de migración real y cada columna una de las piezas del módulo trabajando junta.
Día 1 — El facade arranca a 0% (todo al legacy, legacy=1000). Es el estado de la lección 2: el facade puesto, transparente, sin desviar nada. El gate ve un error_rate de 0% (no hay ruta nueva ejercitada aún) y autoriza subir al primer escalón: subir a 10%.
Día 2 — Ahora a 10% con el modern v1 (con bug). De las 109 requests enrutadas al modern, 99 tienen éxito y 10 caen en fallback (las de webcam). El error_rate es 9.2%, muy por encima del umbral de 1%. El gate decide: HOLD (arreglar). Aquí está el corazón del strangler medido: el sistema no subió el porcentaje porque la ruta nueva no estaba sana. Y fíjate en la protección: esos 10 fallos no afectaron a ningún usuario (el fallback los atendió con el legacy); solo frenaron la promoción. El canary hizo su trabajo —detectó el problema con el 10% del tráfico expuesto—.
Día 3 — El equipo despliega modern v2 (arreglado). A 10%, las 109 requests enrutadas al modern ahora todas tienen éxito: fallback=0, error_rate 0.0%. El gate: subir a 25%. El arreglo se tradujo, de inmediato y automáticamente, en permiso para avanzar. No hubo reunión ni corazonada; el número bajó y el gate abrió.
Días 4, 5, 6 — El ramp se reanuda sin fricción: 25% → 50% → 75% → 100%. En cada escalón el error_rate es 0%, el gate autoriza, y el new% (porcentaje de tráfico en la ruta nueva) sube: 27.1%, 52.0%, 76.5%. Es el burn-down de la lección 7 en vivo: la columna legacy baja 729 → 480 → 235.
Día 7 — A 100%, las 1000 requests van al modern, todas con éxito (ok=1000, fb=0, legacy=0). El burn-down tocó cero: nadie llama al legacy, ni por fallback. El gate de retiro se activa: burn-down=0 → RETIRAR legacy. El modern está completo (v2 maneja webcam), así que apagar el legacy es seguro.
Día 8 — El legacy está RETIRADO. El facade ya no decide nada; todo va al modern por definición. El catalog de Mercado es una rebanada menos de monolito.
El diario cuenta la historia completa del strangler en ocho renglones: un facade que no cambió nada al arrancar, un canary que atrapó un bug sin exponerlo a los usuarios, un gate que frenó y luego autorizó con base en un número, un burn-down que llegó a cero, y un legacy retirado. Cada paso fue incremental (un escalón a la vez), medido (el gate decidió por el error_rate) y reversible (en cualquier día podías bajar el porcentaje). Eso es lo que el módulo 1 prometió que el incremental daría y el rewrite no.
La entrega del capstone
Un capstone entrega artefactos, no solo comprensión. Aquí están los tres:
1. El plan de migración por rebanadas. El monolito de Mercado se migra rebanada por rebanada, empezando por el catalog (alto valor, bajo acoplamiento) y siguiendo con orders, payments, shipping en ese orden, una a la vez y de punta a punta. Cada rebanada recorre las cuatro fases del strangler hasta retirar su legacy antes de empezar la siguiente. (La tabla del plan está arriba.)
2. El código ejecutado. El StranglerFacade completo —facade + modern al lado + desvío por porcentaje con fallback + observabilidad + gate + burn-down + retiro— corrido con su salida literal, el diario de ocho días. No es pseudocódigo ni una descripción: es la migración simulada, reproducible, que puedes correr y modificar (cambia el FIX_DAY, el GATE, el ramp, y observa cómo cambia el diario).
3. La justificación: por qué incremental venció al rewrite. El módulo 1 midió que un rewrite del monolito entregaría cero valor durante años y arriesgaría el sistema entero de una vez. Este proyecto muestra la alternativa ejecutada: el catalog se modernizó sin apagar el negocio (el sistema sirvió tráfico los ocho días), sin exponer a los usuarios a los bugs (el fallback atrapó el problema del día 2), con cada paso medido (el gate), y con el premio cobrado (el legacy retirado, el monolito más pequeño). Donde el rewrite pedía dos años de silencio y una apuesta total, el strangler entregó una rebanada modernizada con riesgo acotado en cada escalón. Esa es la justificación, y ahora la puedes respaldar con un diario ejecutado.
Errores comunes
Abrir varias rebanadas a la vez en vez de terminar una. Qué pasa: entusiasmado, el equipo pone strangler facades en catalog, orders y payments al mismo tiempo. Por qué pasa: parece más rápido avanzar en todo a la vez, y cada facade a 0% se siente barato. Cómo detectarlo: hay tres o cuatro migraciones "en progreso", ninguna cerca de retirar su legacy; el monolito no encogió nada porque ningún legacy se apagó. Cómo corregirlo: una rebanada a la vez, de punta a punta. Termina el catalog —hasta retirar su legacy— antes de tocar orders. El progreso de una migración no se mide en "cuántas rebanadas empezaste" sino en "cuántos legacies retiraste". Cuatro migraciones al 40% valen cero legacies retirados; una migración al 100% vale uno. La disciplina de terminar es lo que cobra el premio.
Un gate que en la práctica siempre aprueba. Qué pasa: el equipo pone un gate pero con un umbral tan laxo (error_rate ≤ 20%) que nunca frena nada, o lo ignora cuando hay prisa. Por qué pasa: el gate que frena es incómodo —el día 2 del diario, el gate detuvo la migración, y eso molesta a quien tiene prisa—. Cómo detectarlo: el traffic_percent sube en cada escalón sin excepción, aun cuando el error_rate era alto; el gate es decorativo. Cómo corregirlo: el gate solo sirve si de verdad puede decir "no". Un umbral realista (error_rate ≤ 1%, como el diario) frena cuando el modern no está sano —y ese freno es el que evita exponer a los usuarios—. Si el gate nunca frena, no es un gate, es un adorno; y sin un gate real, subes el porcentaje por corazonada, que es exactamente lo que la lección 6 combatió. El valor del gate está en las veces que dice "no".
Declarar el capstone terminado en el día 7 (100%) sin llegar al día 8 (retirado). Qué pasa: al ver el traffic_percent en 100% y el burn-down en cero, el equipo da la migración por hecha y no ejecuta el retiro. Por qué pasa: el 100% se siente como el final, y el retiro (borrar el legacy, simplificar el facade) es trabajo sin recompensa visible. Cómo detectarlo: el diario se queda en el día 7; el legacy sigue desplegado indefinidamente aunque nadie lo llame. Cómo corregirlo: el capstone —como el strangler— termina en el día 8, con el legacy retirado, no en el día 7. Todo el módulo insistió en esto: el pago del strangler es retirar el legacy. Un capstone que llega a 100% pero no retira es la migración eterna de la lección 7, y deja el monolito del mismo tamaño. La rebanada está migrada cuando su legacy está borrado, no cuando su tráfico llegó a 100%.
Ejercicios
Ejercicio 1 — Explica el día 2. En el diario, el día 2 el gate decidió HOLD (arreglar) en vez de subir el porcentaje. (a) ¿Qué número disparó esa decisión? (b) ¿Qué habría pasado con los usuarios si el gate hubiera subido a 25% de todos modos? (c) ¿Por qué es una buena señal que la migración se haya detenido ese día?
Ver solución
(a) El error_rate de 9.2%. El modern v1 falló en 10 de las 109 requests que le tocaron (las de webcam), y 10/109 = 9.2%, muy por encima del umbral del gate (1.0%). Ese número disparó el HOLD.
(b) Si el gate hubiera subido a 25% con el modern v1 aún roto, más requests de webcam habrían sido enrutadas al modern y habrían caído en fallback —más carga de doble latencia, y el problema escalando en vez de contenido—. Los usuarios seguirían protegidos por el fallback (nadie vería un error 500), pero estarías exponiendo el bug a más tráfico sin haberlo arreglado, y acercándote al punto donde el volumen de fallbacks se vuelve un problema de rendimiento. Subir con la ruta nueva enferma es lo contrario del canary.
(c) Porque significa que el sistema de seguridad funcionó: el canary detectó el bug del modern con solo el 10% del tráfico expuesto, el fallback protegió a los usuarios de verlo, y el gate impidió que la migración avanzara sobre una base rota. Una migración que se detiene ante un problema real es una migración sana —está usando sus instrumentos—. Lo peligroso sería lo contrario: subir el porcentaje ignorando el error_rate. El HOLD del día 2 es el patrón haciendo justo lo que promete: frenar antes de exponer, no después.
Ejercicio 2 — Cambia un parámetro y predice. Sin correr el código, predice cómo cambiaría el diario si el equipo desplegara el arreglo (FIX_DAY) el día 5 en vez del día 3. (a) ¿Qué pasaría los días 2, 3, 4? (b) ¿Llegaría la migración a 100% dentro de los 8 días? (c) ¿Qué te dice esto sobre la relación entre arreglar rápido y migrar rápido?
Ver solución
(a) Con FIX_DAY=5, el modern sigue en v1 (con bug) los días 2, 3 y 4. El día 2 a 10% da error_rate 9.2% → HOLD. El día 3, todavía v1 a 10%, vuelve a dar 9.2% → HOLD otra vez. El día 4, aún v1 a 10%, otro HOLD. La migración se queda clavada en 10% mientras el bug no se arregle: el gate no deja subir. Tres días perdidos en el mismo escalón.
(b) Difícilmente. El arreglo llega el día 5 (v2, error_rate 0% → sube a 25%). Después necesita los días 6 (25%→50%), 7 (50%→75%), 8 (75%→100%)... y llegaría a 100% el día 8, sin días restantes para verificar el burn-down y retirar. El retiro caería fuera de la ventana de 8 días. Con el arreglo tardío, la migración no alcanza a cerrar en el mismo horizonte.
(c) Que la velocidad de la migración está limitada por la salud de la ruta nueva, no por las ganas de avanzar. El gate no deja subir el porcentaje mientras el modern falle, así que cada día que el bug sigue sin arreglar es un día que la migración no avanza. Arreglar rápido es migrar rápido: el cuello de botella no es el ramp, es la calidad del modern. Esto refuerza la lección 3 (construir el modern bien, desde el contrato y los characterization tests) y la 6 (el gate que mide): un modern sano avanza solo; uno con bugs se atora en el primer escalón.
Ejercicio 3 — El plan de la siguiente rebanada. El catalog quedó migrado (legacy retirado). Ahora toca la siguiente rebanada. (a) Según el plan, ¿cuál sigue y por qué? (b) ¿Qué de esta migración del catalog reutilizarías para la siguiente, y qué esperarías que sea distinto? (c) ¿Por qué payments no fue la primera rebanada?
Ver solución
(a) Según el plan, sigue orders. Se eligió después del catalog porque orders depende del catálogo (necesita datos de productos), así que tener el catalog ya modernizado y estable facilita migrar orders sobre una base limpia. Además, con el catalog completo, el equipo ya recorrió el strangler entero una vez y aprendió el proceso.
(b) Reutilizarías toda la maquinaria del strangler: el patrón del StranglerFacade (enrutar por porcentaje con fallback), la observabilidad de las dos rutas, el gate de promoción y el criterio de retiro por burn-down. La técnica es la misma para cualquier rebanada. Esperarías que sea distinto: la implementación del modern de orders (otra lógica de negocio, más escrituras que el catálogo que casi solo lee), quizás una estrategia de desvío distinta (los pedidos escriben datos, así que el fallback y la consistencia son más delicados que en un catálogo de solo lectura), y probablemente un ramp más lento por ser más crítico. La coreografía es igual; el contenido cambia.
(c) Porque payments maneja dinero, y es el módulo más crítico: un fallo del modern en pagos, aunque el fallback lo atrape, tiene consecuencias mucho más graves que un fallo en el catálogo (un cobro doble, un pago perdido). El principio del plan es empezar por la rebanada de mayor valor y menor riesgo para aprender el proceso donde un error se perdona —el catálogo, que casi solo lee y donde un canary fallido no cuesta dinero—, y dejar la rebanada crítica (payments) para cuando el equipo ya domina el strangler y puede migrarla con el ramp más lento y las verificaciones más estrictas. Se practica donde es barato equivocarse antes de tocar donde es caro.
Resumen y siguiente paso
En este capstone integraste todo el módulo en una sola migración ejecutada: modernizaste el catalog de Mercado de punta a punta con un StranglerFacade que combinó las cuatro fases —facade, servicio nuevo al lado, desvío por porcentaje con fallback y gate, y retiro por burn-down—, corrido como un diario de ocho días. Viste el sistema completo trabajar junto: un canary que atrapó un bug el día 2 sin exponerlo a los usuarios, un gate que frenó la migración y luego la reanudó con base en un número, un burn-down que llegó a cero, y un legacy retirado el día 8. Y produjiste la entrega del capstone: el plan de migración por rebanadas, el código ejecutado, y la justificación —respaldada por el diario— de por qué el incremental venció al rewrite.
Con esto cierras el módulo 3. Dominas el patrón strangler fig: sabes poner un facade transparente, construir el nuevo al lado, desviar el tráfico por las tres estrategias con fallback, observar las dos rutas y decidir con un gate, y retirar el legacy cuando el burn-down llega a cero, todo incremental, medido y reversible.
Lo que sigue extiende esta técnica a los casos que el strangler externo no cubre. El módulo 4 (branch by abstraction) enseña qué hacer cuando no hay una frontera externa donde poner el facade —cuando la cosa que quieres migrar es una función interna del monolito, sin endpoint ni proxy posible—: insertas una capa de abstracción en el código y migras la implementación detrás de ella, con las dos coexistiendo tras un flag, sin una rama de git de larga vida. Y el módulo 5 (extraer un servicio) toma el modern que aquí construimos al lado y lo saca a su propio proceso, con un anti-corruption layer que traduce entre el modelo viejo y el nuevo y con la propiedad de los datos bien definida. El strangler te dio la forma de mover el tráfico; los módulos que siguen te dan la forma de mover el código y los datos que hay detrás.
Recursos
- Martin Fowler, "StranglerFigApplication" (2004) — martinfowler.com/bliki/StranglerFigApplication.html. El texto fundacional del patrón que este capstone ejecuta de principio a fin. Vuelve a leerlo ahora que tienes la mecánica completa: cada frase tendrá un referente concreto. En inglés.
- Sam Newman, Monolith to Microservices (O'Reilly, 2019), cap. 3 completo — la referencia integral para migrar un monolito por rebanadas con el strangler: elegir la primera rebanada, desviar el tráfico, y retirar la funcionalidad del monolito. El mapa del capstone y de las rebanadas que siguen. En inglés.
- Chris Richardson, "Pattern: Strangler application" — microservices.io/patterns/refactoring/strangler-application.html. La ficha del patrón vista ahora como un todo: el resultado es un monolito que encoge rebanada por rebanada hasta desaparecer. En inglés.
- Paul Hammant, "Legacy Application Strangulation: Case Studies" (2013) — paulhammant.com/2013/07/14/legacy-application-strangulation-case-studies. Casos reales de migraciones completas por estrangulamiento, con los aciertos y los tropiezos —el complemento práctico a la simulación de este capstone—. En inglés.