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.
De la idea a la práctica
Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.
Cómo funciona
- Interceptar. Coloca una fachada (API gateway, proxy, BFF) delante del sistema heredado. Al principio enruta todo al viejo.
- Extraer. Elige una capacidad delimitada, constrúyela en el sistema nuevo y redirige su tráfico.
- Retirar. Elimina el código y los datos que ya no se usan en el heredado.
- 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.