Hay una conversación que ocurre en muchas empresas más o menos una vez al año. Alguien señala que la aplicación interna de la que todos dependen se escribió hace mucho, sobre un framework del que ya nadie habla, por gente que en su mayoría ya no trabaja aquí. Otro pregunta cuánto costaría reemplazarla. El número que vuelve es grande. Todos coinciden en que es importante. No pasa nada. Doce meses después la misma conversación arranca otra vez, desde el principio.
Se atora porque la pregunta está mal. “¿Cuánto costaría reemplazar esto?” no tiene una respuesta útil, porque la mayoría de estas aplicaciones no se deben reemplazar. Se deben mover, por partes, en un orden, dejando algunas partes exactamente donde están.
“Está viejo” no es una razón
La edad no es un defecto. Una aplicación que lleva doce años funcionando bien ya demostró algo que una nueva no. Si genera dinero, la gente que la usa la domina y nada de ella está en llamas, entonces la versión del framework es un dato, no un problema.
Lo que sí obliga a decidir es más acotado, y vale la pena decirlo con franqueza, porque si nada de esto aplica quizá estés a punto de gastar sin retorno:
- No consigues contratar para eso. Es el detonante real más común y del que menos se habla. Cuando el grupo de personas dispuestas a tocar un código se vuelve demasiado chico, el riesgo deja de ser técnico.
- Algo de lo que depende dejó de tener soporte. No la aplicación. Algo por debajo: el sistema operativo, el framework, la versión de la base de datos, una integración de pagos, una librería con una vulnerabilidad conocida y sin versión corregida.
- El negocio necesita algo que la arquitectura no puede dar. Acceso móvil, una API para un socio, inicio de sesión único, una integración que asume un flujo de autenticación moderno.
- Está bloqueando otra cosa. Salir de un centro de datos, un requisito de cumplimiento, una adquisición, una actualización de ERP que cambia el contrato por debajo.
- El costo de un cambio pequeño se volvió absurdo. Cuando un cambio de dos líneas toma tres semanas porque nadie lo puede probar con seguridad, eso es un impuesto real, medible, y se acumula.
Si alguna de esas es cierta, el proyecto tiene caso de negocio. Si ninguna lo es, la recomendación honesta es hacer el trabajo de seguridad y dependencias, dejar por escrito cómo se comporta la cosa, y revisarlo en un año. Preferimos decir eso a vender una reescritura que nadie necesitaba.
Las rutas, y lo que cuesta cada una
Web Forms
Esta es la dura. ASP.NET Web Forms solo corre sobre .NET Framework. Nunca se trajo hacia adelante y nunca se va a traer. No hay capa de compatibilidad ni conversión automática que produzca una aplicación moderna funcionando, porque todo el modelo, con su ciclo de vida de página, view state y controles de servidor, no tiene equivalente del otro lado.
Así que la capa de interfaz es una reescritura. Lo que no lo es, es todo lo que está detrás. En la mayoría de las aplicaciones Web Forms que revisamos, buena parte del valor real vive en clases de lógica de negocio y acceso a datos que son C# ordinario y se mueven a .NET actual con mucha menos fricción de la que cualquiera espera. La forma realista es: conservar la lógica, portarla, y reconstruir las pantallas sobre Razor Pages, MVC o Blazor según qué tan interactivas necesiten ser.
La trampa es dimensionar toda la aplicación como una reescritura porque el front-end lo es. Así es como un proyecto de nueve meses se cotiza para algo más cercano a tres.
Servicios ASMX y WCF
ASMX está en la misma posición que Web Forms: solo .NET Framework, sin camino hacia adelante. WCF tiene más matices, porque existe CoreWCF y puede llevar un servicio adelante casi intacto si de verdad necesitas la pila WS-*, los contratos SOAP o los transportes.
Normalmente no los necesitas. La mayoría de los endpoints ASMX y WCF internos hacen algo que una API JSON simple sobre HTTP hace de forma más sencilla, y quienes los consumen son tuyos y los puedes actualizar. El destino habitual son las minimal APIs o los controladores de ASP.NET Core, con el contrato limpiado en el camino en vez de reproducido tal cual. Mantener vivo un sobre SOAP solo porque estaba ahí en 2011 es una decisión que conviene tomar a propósito y no por inercia.
Donde no puedas cambiar a los consumidores, porque del otro lado hay un socio o un dispositivo, corre la API nueva en paralelo y deja un endpoint delgado de compatibilidad. Sale mucho más barato de lo que suena y desacopla tu calendario del de ellos.
WinForms, y la migración que la gente hace mal
WinForms no está muerto, y esta es la corrección que más dinero ahorra. WinForms y WPF corren sobre .NET actual, en Windows. Una aplicación WinForms de línea de negocio puede pasar de .NET Framework a .NET 10 y seguir siendo WinForms. Te llevas el runtime moderno, dependencias al día, mejor rendimiento y una plataforma con soporte, sin reescribir una sola pantalla.
Eso importa porque la respuesta refleja a “tenemos una app vieja en WinForms” cada vez es más “reescríbela en MAUI”, y para muchas aplicaciones esa es simplemente la herramienta equivocada. MAUI es para multiplataforma: iOS, Android, Windows y macOS desde un solo código. Si tu aplicación corre en escritorios Windows dentro de tu propio edificio y siempre va a ser así, MAUI no te compra nada y te cuesta una reescritura completa de la interfaz.
MAUI es la respuesta correcta cuando el requisito de verdad cambió de forma. Tus técnicos de campo la necesitan en el celular. Tu equipo de ventas la necesita en un iPad. Quieres un solo código para escritorio y móvil en vez de dos equipos. Esas son razones reales, y cuando aplican vale la pena hacer el trabajo bien. Escribimos el detalle de esa ruta por separado en la guía de migración de Xamarin a .NET MAUI, y buena parte aplica igual viniendo de WinForms.
El orden que funciona: llegar primero a .NET actual, todavía en WinForms, y tratar el paso a MAUI como una decisión aparte tomada después por sus propios méritos. Hacer las dos a la vez es como estos proyectos terminan sin poder decir qué fue lo que se rompió.
La opción que nadie cotiza
Déjala. Parcha el stack de abajo, arregla las dependencias con vulnerabilidades conocidas, escribe qué hace la aplicación y ponla bajo un acuerdo de mantenimiento. Para una aplicación que funciona y no está bloqueando nada, esta es con frecuencia la opción de mayor retorno disponible, y es la que nunca te va a ofrecer quien vende una reconstrucción.
Dónde acelera de verdad la IA y dónde no
Migrar es sobre todo un problema de traducción a través de una frontera conocida, y eso es justo en lo que las herramientas de IA actuales son buenas. Usadas con disciplina cambian la economía de forma material. Usadas como varita mágica producen código seguro de sí mismo, plausible y equivocado, a un ritmo que ningún revisor humano alcanza.
Dónde ayuda
- Leer el código y decirte qué hay dentro. Cada pantalla, cada procedimiento almacenado, cada rama de lógica de negocio, convertidos en un registro estructurado de qué hace la aplicación y por qué. En un código que nadie ha entendido por completo en una década, esta es con diferencia la aplicación de mayor valor, y es lo bastante tediosa a velocidad humana como para que nunca se haga.
- La traducción mecánica. Code-behind de Web Forms a un controlador y un view model. Método ASMX a un endpoint de minimal API. Acceso a datos viejo a algo actual. Son transformaciones consistentes y repetitivas, y la consistencia a volumen es precisamente la fortaleza.
- Generar las pruebas que nunca tuviste. La aplicación vieja es una especificación funcional de su propio comportamiento hasta el momento en que la apagas. Caracterizar ese comportamiento como pruebas, mientras sigue corriendo, te da contra qué contrastar la nueva. Esta sola práctica separa las migraciones que salen bien de las que salen mal, y casi nadie la hacía antes de que se volviera barata.
- Triaje de dependencias y vulnerabilidades. Averiguar cuáles de cuatrocientos paquetes importan de verdad, qué se rompe si los mueves y en qué orden.
Dónde no ayuda
- Decidir qué conservar. Parte de lo que hace tu aplicación es una regla de negocio deliberada. Parte es un rodeo a una limitación que ya no existe. Parte es un bug al que todos se adaptaron en silencio hace años. Distinguirlos exige hablar con quienes la usan. Ningún modelo sabe cuál es cuál, y un “bug” reescrito con confianza que en realidad era una regla es como pierdes un mes.
- Arquitectura. Si esto debe ser un servicio o cuatro, si esa cola es necesaria, cuáles son los modos de falla cuando una dependencia va lenta. Son decisiones de criterio cuyas consecuencias aparecen en el año tres.
- Cualquier cosa que no verifiques. Código generado que compila no es código generado que sea correcto. La carga de revisión es real, no desaparece, y un equipo que se la salta convierte una migración en una caída.
El encuadre honesto: la IA no elimina el proyecto. Elimina casi toda la arqueología, casi toda la traducción mecánica y el pretexto para no tener una suite de pruebas. Eso es una fracción grande del costo y la mayor parte del riesgo, que es una afirmación muy distinta de “la IA reescribe tu app”.
Blindar el futuro, es decir, la próxima migración
“Blindar el futuro” suele no significar nada. Concretado, significa una sola cosa: hacer más barata la siguiente de estas. Los frameworks van a seguir cambiando. La meta no es elegir un stack que dure para siempre, porque ninguno dura. La meta es quedar en posición de que mudarse otra vez sea un proyecto y no una crisis.
Lo que de verdad logra eso, en orden aproximado de valor:
- Una suite de pruebas que describa el comportamiento. El mayor determinante de si una migración futura es segura. Si te llevas una sola cosa de este artículo, que sea esta.
- Lógica de negocio que no viva en la interfaz. La razón por la que duelen las migraciones de Web Forms es que una década de reglas terminó dentro de archivos de code-behind. La lógica que vive en su propia capa se mueve a lo que venga después casi gratis.
- Requerimientos escritos. No documentación del código, que se pudre. Un registro de las decisiones y sus porqués, que no.
- Dependencias aburridas y actuales. Menos librerías, elegidas por estar mantenidas y no por ser ingeniosas, actualizadas por rutina en vez de a las carreras.
- Configuración y secretos fuera de la aplicación. Barato de hacer, y elimina toda una categoría de dolor en la migración.
- Un despliegue que puedas correr cuando quieras. Si publicar es difícil, todo lo que viene después de publicar también lo es.
Qué expone en realidad un stack envejecido
La seguridad en aplicaciones heredadas se discute en abstracto, lo que la vuelve fácil de aplazar. En concreto, en las aplicaciones que auditamos aparece la misma lista corta:
- Un framework o runtime fuera de soporte. .NET Framework 4.6.x perdió soporte en abril de 2022, y muchas aplicaciones siguen ahí. Pasar a 4.8 suele ser sencillo y es una mejora real aunque nunca salgas de .NET Framework.
- Un sistema operativo fuera de soporte. Windows Server 2012 R2 salió de soporte en octubre de 2023 y sigue en producción en más lugares de los que a nadie le gustaría admitir.
- Configuración de TLS y cifrados heredada de la instalación original. Versiones viejas de protocolo aún habilitadas, que reprueban escaneos modernos y cada vez más rompen integraciones con proveedores de pago y socios.
- Dependencias con vulnerabilidades publicadas y correcciones disponibles. La mayoría poco glamorosa de los hallazgos reales. Nada exótico, simplemente nunca se hizo.
- Autenticación anterior a la práctica actual. Manejo de sesión casero, contraseñas con un algoritmo que estaba bien en 2013, ninguna ruta a multifactor.
- Secretos en archivos de configuración. Guardados en el control de versiones, legibles por todo el que alguna vez haya bajado el repositorio.
Casi nada de eso requiere la reescritura. Requiere que alguien mire, y luego haga el trabajo en orden de prioridad. Que es el argumento de la última sección.
Revisión, auditoría, y la versión incómoda de esta conversación
A veces el trabajo útil no es una migración. Es una lectura externa del código y del equipo que lo rodea, entregada a quien tiene que decidir y ha venido recibiendo respuestas contradictorias.
Lo que produce:
- Una foto del as-built. Qué es realmente la aplicación, de qué depende, dónde se concentra el riesgo, qué es código muerto y qué solo lo parece.
- Una postura de seguridad y dependencias. Hallazgos ordenados por si son de verdad alcanzables, no un volcado de escáner con cuatrocientos críticos que nadie va a leer.
- Un conjunto de opciones costeadas. Quedarse y mantener, mover por partes, reconstruir. Con números reales y el razonamiento a la vista, incluido el caso de hacer lo mínimo.
- Una lectura honesta de la entrega. Si el equipo puede ejecutar el plan, qué falta, y si la restricción es de gente, de proceso o de herramientas. Esta es la parte que los clientes piden en privado y muchas veces es la pregunta de fondo.
Diremos cuando un equipo interno está bien y no nos necesita, porque una revisión que siempre concluye “contrata al que revisa” no vale nada para quien la lee.
Una secuencia que funciona
- Captura el as-built primero, mientras el sistema viejo sigue corriendo. Antes de cualquier trabajo en la plataforma nueva. La ventana se cierra cuando se apaga, y todo lo que sigue sale más barato si esto va primero.
- Haz de inmediato el trabajo de seguridad y dependencias. Es independiente de cualquier otra decisión, es comparativamente barato, y es la parte con fecha límite puesta por alguien más.
- Caracteriza el comportamiento como pruebas contra el sistema viejo, para que el nuevo tenga contra qué medirse.
- Mueve el runtime antes que la arquitectura. Primero .NET actual, misma forma. WinForms se queda en WinForms. Después decides sobre la interfaz, aparte y por sus propios méritos.
- Migra en rebanadas que puedan salir a producción. Un servicio, un grupo de pantallas, una integración. Lo que no puede salir en seis meses tampoco se puede corregir en seis meses.
- Corre viejo y nuevo en paralelo hasta un cambio real. Con usuarios de verdad en la ruta nueva antes de apagar la vieja.
Las conclusiones
La mayoría de las aplicaciones .NET heredadas están mejor de lo que sugiere la conversación sobre ellas. Que el framework esté pasado de moda no es un problema de negocio. No poder contratar, no poder parchar y no poder cambiarla con seguridad sí son problemas de negocio, y tienen arreglos distintos con precios distintos.
Consigue primero el inventario honesto. Haz el trabajo de seguridad pase lo que pase. Mueve el runtime antes que la arquitectura. Usa la IA para la arqueología y la traducción, no para el criterio. Y desconfía de quien recomienda una reescritura completa antes de haber leído tu código.
¿Tienes una de estas en tu registro de riesgos?
Construimos sobre .NET 10 y .NET MAUI, y hemos pasado mucho tiempo dentro de aplicaciones que escribió otra gente y que nadie entendía del todo. Si quieres una lectura directa de lo que cuestan de verdad tus opciones, ya sea una migración, una pasada de seguridad y dependencias, o una revisión externa del código y del equipo, cuéntanos qué estás operando. Te diremos si la respuesta es dejarla en paz, y eso es un resultado genuino y no una cortesía. También puedes leer cómo abordamos el software a la medida y el móvil multiplataforma.