Alejandría

Busca en Alejandría

Técnicas

Strangler fig

Moderniza un sistema heredado sustituyéndolo por partes, sin una gran reescritura.

01

En pocas palabras

Estrategia de migración incremental en la que un nuevo sistema crece alrededor del antiguo, interceptando y reemplazando funcionalidades hasta que el heredado puede retirarse.

Qué problema resuelve

Reescrituras completas que tardan años, persiguen un objetivo móvil y no entregan valor hasta el final.

Cuándo utilizarlo

Monolitos o sistemas heredados críticos que no se pueden detener. Ejemplo: sacar la gestión de cobranza de un core bancario antiguo.

02

De la idea a la práctica

Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.

Cómo funciona

  1. Interceptar. Coloca una fachada (API gateway, proxy, BFF) delante del sistema heredado. Al principio enruta todo al viejo.
  2. Extraer. Elige una capacidad delimitada, constrúyela en el sistema nuevo y redirige su tráfico.
  3. Retirar. Elimina el código y los datos que ya no se usan en el heredado.
  4. Repite hasta que el heredado esté vacío o reducido a lo que no compensa migrar.
             ┌─────────── /cobranza/** ──▶ Servicio nuevo de cobranza
Clientes ──▶ Fachada
             └─────────── resto ─────────▶ Monolito heredado

Elegir qué extraer primero

Criterio Por qué
Alto valor de cambio Lo que más se modifica es lo que más duele en el heredado
Bajo acoplamiento de datos Menos sincronización entre bases
Límite de dominio claro Un bounded context es un buen candidato
Riesgo controlable Empieza por algo que puedas revertir

Evita empezar por lo más crítico y acoplado (el cálculo de intereses) o por lo trivial que nadie nota.

El problema de los datos

El código se migra con relativa facilidad; los datos no. Patrones habituales de Patterns of Legacy Displacement:

  • Event interception: capturar cambios del heredado (CDC) para alimentar el nuevo.
  • Legacy mimic: el nuevo sistema escribe también en el heredado mientras otros módulos aún lo leen.
  • Transitional architecture: piezas temporales (sincronizadores, adaptadores) que se planifica eliminar.
  • Divert the flow: cambiar primero los flujos de entrada para que el nuevo sea fuente de verdad.

Declara explícitamente quién es dueño de cada dato en cada fase.

Verificar antes de cambiar el tráfico

  • Shadow / dark launch: enviar la petición a ambos sistemas, servir la respuesta del viejo y comparar.
  • Parallel run: ejecutar ambos durante un periodo y conciliar resultados (útil en cálculos financieros).
  • Canary: desviar un porcentaje creciente, como en 1% canary.

Antipatrones frecuentes

  • Arquitectura transicional permanente: los sincronizadores temporales viven diez años.
  • Migrar sin retirar: el heredado sigue recibiendo cambios «por si acaso».
  • Reproducir los defectos del modelo viejo en el nuevo. Usa una anti-corruption layer.

Enrutamiento progresivo en la fachada

# Regla ilustrativa en un gateway (APISIX, Envoy, NGINX…)
routes:
  - match: { path: /cobranza/*, header: { x-pais: CO } }
    split:
      - { upstream: cobranza-nuevo, weight: 20 }
      - { upstream: monolito, weight: 80 }
  - match: { path: /cobranza/* }
    upstream: monolito
  - match: { path: /* }
    upstream: monolito

Avanzar por segmentos (un país, un producto, un canal) limita el impacto y facilita comparar resultados. Ver Apache APISIX para un gateway con división de tráfico dinámica.

Parallel run en cálculos financieros

public PlanPagos calcular(Credito credito) {
    PlanPagos legado = sistemaLegado.calcularPlan(credito);           // sigue siendo la respuesta
    executor.submit(() -> {
        try {
            PlanPagos nuevo = servicioNuevo.calcularPlan(credito);
            var diferencias = Comparador.diferencias(legado, nuevo, TOLERANCIA_CENTAVOS);
            metricas.counter("parallel_run", "resultado", diferencias.isEmpty() ? "igual" : "distinto").increment();
            if (!diferencias.isEmpty()) registro.guardar(credito.id(), diferencias);
        } catch (Exception e) {
            metricas.counter("parallel_run", "resultado", "error").increment();
        }
    });
    return legado;
}

Las diferencias registradas se analizan con negocio: algunas son defectos del sistema nuevo, otras revelan defectos históricos del heredado que hay que decidir si se replican.

Panel de seguimiento de la migración

Indicador Para qué
% de tráfico servido por el sistema nuevo Avance real, por capacidad
Capacidades migradas / retiradas del heredado Que la migración también reste, no solo sume
Tasa de diferencias en parallel run Preparación para cambiar la fuente de verdad
Incidentes atribuibles a la migración Coste en estabilidad
Coste de la arquitectura transicional Sincronizadores y adaptadores pendientes de retirar

Comunicación con negocio

Presenta la modernización como una secuencia de resultados («en Q1 los cambios en cobranza se despliegan en días en lugar de meses») y no como un proyecto técnico de duración incierta. Cada hito debe poder detenerse sin dejar el sistema peor que antes: esa es la principal ventaja frente a una reescritura.

Criterios de implementación

Planifica en hitos de negocio, no técnicos: «cobranza en el sistema nuevo» y no «capa de datos al 60 %». Mide el porcentaje de tráfico y de código retirado del heredado. Apóyate en herramientas de IA para migraciones de código y OpenRewrite para tareas mecánicas, y registra cada fase en un ADR.

Continúa en las fuentes

Documentación oficial para verificar detalles y explorar más.