La migración de ColdFusion empieza antes de vencer la licencia
Planifica una migración de ColdFusion que mantenga el tráfico, separe el comportamiento CFML del runtime y retire la licencia con pruebas.

Decidir no renovar ColdFusion fija una fecha, pero no crea un plan de migración. El trabajo consiste en conservar cada comportamiento del que dependen los usuarios y los sistemas conectados mientras el runtime CFML todavía sirve como referencia fiable. Si el equipo empieza convirtiendo etiquetas a otro lenguaje, reproducirá la parte menos útil del sistema y pasará por alto contratos ocultos en resultados de base de datos, sesiones, tareas programadas, entregas de archivos y gestión de errores.
Una migración de ColdFusion segura mantiene la aplicación actual atendiendo tráfico mientras el reemplazo asume rutas y tareas en partes medibles. El orden importa: inventariar el comportamiento real, fijar el límite de la aplicación, aislar la semántica de datos, mover entradas no visuales y transferir lecturas y escrituras ruta por ruta. El servidor viejo se retira solo cuando el tráfico grabado demuestra paridad y la vuelta atrás deja de ser útil.
Tratar la no renovación como un límite comercial
La no renovación dice cuándo la organización quiere dejar de comprar el producto. Por sí sola no dice qué hará un servidor instalado ese día. Las ediciones y licencias de ColdFusion difieren, y Adobe cambió la versión 2025 de claves de serie a suscripciones Named User Licensing y Feature Restricted Licensing. Las instalaciones anteriores pueden tener otras condiciones. Revisa el pedido, contrato, registros de despliegue, fechas de soporte y método de activación de la versión productiva. Nadie debe deducir derechos legales porque un proceso siga arrancando.
Separa cuatro fechas: decisión de renovación, fin de soporte de la versión, posible evento de activación o derecho, y día en que producción puede funcionar sin CFML. Pueden ser distintas. Compras o asesoría jurídica resuelven el uso permitido; operaciones prueba la activación en un clon aislado. Ninguna respuesta sustituye a la otra.
Mantén estable el entorno licenciado durante la salida. Congela cambios de runtime, JVM, drivers y limpiezas oportunistas de frameworks salvo que la seguridad obligue. Cada cambio simultáneo debilita la referencia. Aplica actualizaciones admitidas, limita el acceso administrativo y registra JVM, conectores, hotfixes, mappings, fuentes de datos, tareas y servicios externos exactos.
No prometas que el servidor fallará a medianoche ni que funcionará para siempre. Ambas afirmaciones son conjeturas hasta leer las condiciones aplicables y probar el mecanismo de derecho. La fecha útil es la que sostienen las pruebas.
Inventariar comportamientos, no extensiones
Contar archivos CFM y CFC no produce un mapa del sistema. Empieza por puntos de entrada productivos y sigue qué lee, cambia, emite y llama cada uno. Una plantilla pequeña puede cargar includes, invocar un CFC, alterar la sesión, ejecutar SQL, generar un PDF, enviar correo y redirigir por un manejador de errores. Sus líneas no miden el riesgo.
Crea un registro de rutas y tareas con una fila por entrada observable. Guarda método y ruta HTTP, autenticación, campos importantes, estado y tipo de respuesta, cookies modificadas, tablas leídas o escritas, archivos o mensajes, llamadas externas y responsable capaz de validar el resultado. Incluye tareas programadas, métodos CFC remotos, servicios web, procesadores de archivos, mappings del administrador y operaciones manuales fuera del repositorio.
Las dependencias incómodas suelen vivir fuera de CFML. ColdFusion Administrator puede contener credenciales, correo, argumentos JVM, reglas sandbox, rutas de custom tags, tareas y conectores web. Application.cfc establece parte del comportamiento, pero la configuración del servidor puede cambiar el significado del código. Expórtala y crea un inventario textual comparable. Una captura de pantalla no permite un diff fiable.
Registra el uso real antes de eliminar. Guarda plantilla de ruta, estado, duración, rol y una huella respetuosa con la privacidad. Para tareas, registra inicio, fin, resultado y artefacto comercial. Una página ausente de los logs puede ejecutarse en el cierre anual. Bórrala solo cuando su dueño confirme que nadie consume su comportamiento.
Convertir Application.cfc en el primer límite
Application.cfc define el ciclo de vida que el reemplazo debe reproducir o cambiar deliberadamente. Lee onApplicationStart, onSessionStart, onRequestStart, onRequest, onRequestEnd, onError y el manejo de plantillas ausentes como un flujo único. Revisa también Application.cfm y OnRequestEnd.cfm. Adobe CFML Reference indica que, cuando existe Application.cfc, ColdFusion ignora esos archivos CFM dentro del contexto. La ubicación decide qué ciclo se ejecuta.
Clasifica cada scope por duración y dueño. application es estado compartido del proceso, session pertenece al usuario, request es transitorio, server puede cruzar aplicaciones y variables cambia entre plantillas y componentes. El reemplazo no necesita los mismos nombres, pero debe conservar caducidad de sesión, idioma, autorización, correlación y datos de referencia visibles.
No arrastres memoria de proceso por accidente. Un CFC guardado en application puede cachear datos que el nuevo servicio acaba de modificar. Asigna a cada caché fuente, vencimiento, invalidación y dueño. Durante el doble funcionamiento, desactivar una caché dudosa suele ser más seguro que recrear sus rarezas.
Convierte el ciclo de vida en middleware y servicios antes de tocar la presentación. Autenticación, resolución de tenant, correlación, mapeo de excepciones y headers pertenecen al borde nuevo. Con pruebas con nombre, una ruta migrada no puede saltarse reglas y el proxy adjunta el mismo identificador a ambas respuestas.
Los CFC contienen varios contratos
Un CFC puede ser objeto interno, endpoint remoto, singleton con estado o envoltura SQL. Convertir cada .cfc en una clase conserva archivos pero oculta el contrato público. Clasifica cada componente por la forma en que lo llaman y el estado que posee.
Para métodos remotos, registra nombre, formas de argumentos, valores predeterminados, controles de acceso, serialización, estado HTTP y errores. Los clientes CFML suelen tolerar mayúsculas y tipos flexibles que un handler TypeScript tipado rechazará. Un valor que parece array puede serializarse con columnas y datos propios de una query. Captura los bytes vistos por clientes reales, no el objeto del depurador.
En CFC internos, sigue primero las llamadas. Un componente creado con createObject desde plantillas puede ser un servicio de petición. Uno en application puede necesitar control de concurrencia. Un método remote sin consumidor externo no debe convertirse en API pública solo porque el código lo permitía. La exposición es comportamiento por verificar.
Define contratos de reemplazo como fixtures claras:
{"request":{"method":"GET","path":"/account/orders","sessionRole":"buyer"},"response":{"status":200,"contentType":"text/html; charset=UTF-8","setCookieNames":[],"bodyNormalizers":["csrf-token","generated-at"]}}
La fixture no impone arquitectura. Define qué significa paridad y qué campos pueden variar. Añade casos negativos para sesiones ausentes, argumentos mal formados, envíos duplicados y timeouts. Los errores también tienen consumidores.
Separar la sopa de etiquetas antes de traducir
Las plantillas CFML mezcladas contienen control de petición, decisiones de negocio, acceso a datos y HTML. Una traducción mecánica enreda lo mismo en otro lenguaje. Identifica decisiones y contrato de respuesta e impleméntalos detrás del límite de ruta existente.
Una página con valores cfparam, include de autorización, dos cfquery, cfloop, escape cfoutput y redirección tras formulario tiene un contrato mayor que su marcado. Incluye valores por defecto, estado y destino, doble envío, orden de query, presentación de null, codificación, cookies y quizá un mensaje esperado por un cliente. Escríbelo antes de modificar.
Mueve la presentación pura al final de cada ruta. Primero reproduce modelo de petición y operaciones de datos; luego renderiza un view model estable en el nuevo cliente o plantilla. Así una interfaz TypeScript no depende de queries sin documentar y la comparación HTML puede normalizar tokens variables sin ocultar diferencias comerciales.
No rediseñes cada pantalla durante la salida. Un rediseño cambia navegación, validación, accesibilidad y soporte a la vez. Parece progreso visible, pero es un error cuando manda la licencia. Conserva el recorrido, retira el runtime y mejora después con criterios separados.
El objeto query forma parte del contrato
La capa query de ColdFusion no es solo transporte SQL. La documentación de Adobe describe cfquery como un objeto con filas y propiedades RecordCount, ColumnList, SQL, Cached, SQLParameters y ExecutionTime. Las plantillas lo iteran, tratan columnas como arrays, esperan nombres sin distinguir mayúsculas, ejecutan Query of Queries o lo serializan. Un driver PostgreSQL que devuelve filas no reproduce esa semántica.
Inventaría cada fuente y clasifica queries como lectura, escritura, transacción, procedimiento, Query of Queries, SQL dinámico o caché. Localiza cfqueryparam ausentes, pero no mezcles una renovación general de seguridad con paridad salvo exposición inmediata. Parametrizar puede cambiar conversiones implícitas y planes, por lo que necesita pruebas.
Crea un adaptador que devuelva registros de dominio explícitos en vez de imitar una query universal. En el límite viejo captura columnas, orden, null, precisión, fechas y zonas, recuento, claves generadas y errores. Compáralos en el nuevo límite. Conserva orden solo con ORDER BY; si un cliente depende del orden accidental, hazlo explícito.
Adobe documenta QueryExecute con SQL, parámetros y opciones, aceptando arrays o structs. Ayuda al refactor previo porque muestra SQL y enlaces. No resuelve la migración. El contrato difícil está en forma del resultado, transacciones, configuración y código consumidor.
Usa una ficha pequeña por operación importante:
operation: findOpenOrders
inputs: customerId integer, cutoff timestamp UTC
reads: orders, order_items
ordering: orders.created_at DESC, orders.id DESC
nulls: shipped_at remains null
precision: total_amount decimal(18,2), never float
errors: missing customer returns empty rows; unavailable DB returns dependency error
Esta ficha evita que la nueva ruta entregue filas correctas en otro orden, redondee dinero como coma flotante o convierta null de base de datos en texto vacío.
Mover tareas antes que páginas concurridas
Tareas programadas, procesadores, feeds y métodos remotos estrechos son buenos primeros cortes porque sus entradas y salidas se registran con facilidad. También exponen rutas de archivos, cuentas de servicio, correo, proxy, idioma, zona horaria y reintentos que un plan centrado en páginas olvida.
No copies solo una expresión cron. Averigua si ColdFusion impedía solapamiento, cómo se reintentaban fallos, dónde se escribía el log, qué directorio suponía y si una ejecución parcial era repetible. Añade una clave de idempotencia o checkpoint si el proceso único daba protección accidental. Ejecuta en sombra con entradas copiadas antes de permitir escrituras.
Las llamadas CFC remotas y feeds sirven para el proxy. Envía un grupo interno al reemplazo, compara respuestas tras una normalización aprobada y aumenta la autoridad. Duplicar escrituras en sombra causa efectos dobles. Compara en una base restaurada o deja que solo una versión confirme cambios.
Esta fase prueba despliegue, secretos, observabilidad, rollback y propiedad con poca exposición. Si el equipo no opera una tarea migrada durante un fallo, no está listo para rutas de cuentas o informes.
Poner al proxy al mando del orden
Un reverse proxy o balanceador debe decidir qué implementación posee cada ruta. DNS es demasiado grueso y un flag dentro de CFML todavía obliga a usar el runtime viejo. Operaciones necesita una tabla visible que pueda cambiar sin desplegar las dos aplicaciones.
Elige cortes explícitos: rutas, métodos, hosts, tenants o grupos de usuarios estables. Evita porcentajes en escrituras con estado hasta compatibilizar sesión y datos. Un usuario que envía un formulario a un lado y recibe la redirección del otro descubre diferencias de tokens, mensajes y caché.
Un orden práctico es:
- Activos estáticos y endpoints de salud sin estado comercial.
- Tareas y APIs estrechas de lectura con fixtures.
- Páginas de lectura mediante el nuevo adaptador.
- Rutas de escritura con idempotencia, transacción y rollback.
- Autenticación, creación de sesión, uploads, exportaciones y rutas transversales.
Mantén una base autoritativa por corte. La doble escritura crea conciliación cuando más se necesita un retorno limpio. Prefiere un escritor, cambios compatibles y captura o auditoría. Si el esquema Postgres objetivo difiere, introdúcelo tras un adaptador y mueve la propiedad tabla por tabla.
El tráfico grabado convierte la paridad en prueba
Las pruebas unitarias demuestran ejemplos elegidos; el tráfico productivo muestra entradas reales. Captura peticiones y resultados con controles de privacidad, reprodúcelos de forma aislada y compara estado, headers, cuerpo normalizado, efectos en datos y efectos externos. Tokeniza campos sensibles sin perder las diferencias que usa el negocio.
Clasifica cada diferencia: cambio intencional, campo volátil, defecto fuente aceptado temporalmente o defecto nuevo. Los normalizadores deben ser estrechos y revisables. Ignorar cualquier fecha u ordenar todos los arrays puede hacer parecer correcta una respuesta rota. Normaliza solo un campo CSRF, id o reloj concreto cuando el contrato permita variar.
Una comprobación HTTP reproducible es sencilla:
curl -sS -D old.headers -o old.body -b session.txt https://old.internal/orders/1042
curl -sS -D new.headers -o new.body -b session.txt https://new.internal/orders/1042
El artefacto útil es el informe, no los comandos. Guarda huella, estados, headers distintos, comparación del cuerpo, cambios de datos, efectos y decisión del revisor. Exige pruebas para éxitos, fallos de autorización, entradas inválidas, resultados vacíos, reintentos y dependencias caídas.
CodeHero aplica este modelo a escala de código: la plataforma lee todo el árbol multilenguaje y un harness de paridad prueba el reemplazo contra tráfico productivo grabado. Es la medida correcta aunque construyas el harness, porque la retirada de licencia debe basarse en comportamiento observado, no archivos convertidos.
Cambiar escrituras con el rollback intacto
Una ruta puede escribir cuando el reemplazo ha demostrado semántica de datos y el camino viejo puede volver sin reparar estado incompatible. Usa expand-and-contract: añade estructuras compatibles, despliega lectores tolerantes, mueve el escritor, verifica y elimina lo viejo solo cuando caduque el rollback.
Las sesiones requieren una decisión. Puedes compartir store y cookie, traducirlas en el proxy o pedir nueva autenticación controlada al grupo migrado. Compartir sirve solo si serialización, caducidad, rotación y cifrado coinciden. Volver a entrar suele ser más limpio, pero protege formularios activos.
Para uploads y archivos, define propiedad fuera del disco local. Confirma nombres, permisos, antivirus existente, retención y visibilidad atómica. Un reemplazo que escribe en el contenedor mientras CFML lee un recurso compartido supera pruebas y después pierde archivos.
Fija disparadores de rollback antes del cambio: defecto de paridad protegido, cambio de errores, cola creciente, invariante rota o efecto imposible de conciliar. Nombra quién revierte y qué ocurre con escrituras ya aceptadas. Devolver tráfico sin conciliar datos no es rollback.
Mueve una familia limitada cada vez y conserva el código viejo desplegable. Tras la ventana de pruebas y aceptación, retira a la aplicación antigua el derecho de escribir esa ruta. El retorno se convierte en una opción con vencimiento deliberado.
Separar operaciones de la consola antigua
La migración sigue incompleta mientras un operador necesite ColdFusion Administrator para entender o recuperar el servicio. Mueve health checks, logs estructurados, ids, historial de tareas, controles y dependencias al sistema operativo habitual. Conserva el significado de alertas, no una consola por sus botones conocidos.
Escribe un runbook por carga mientras quien opera CFML todavía puede comparar. Debe explicar despliegue, pausa, reintento, rollback, inspección de peticiones, conciliación parcial, rotación de secretos y conexión SQL. Pruébalo en un fallo controlado.
Haz lo mismo con la configuración. Fuentes, mappings, correo, zonas y propiedades JVM son entradas ocultas. Revisa la configuración nueva, separa secretos y falla con claridad si falta un valor. Registra la equivalencia de cada ajuste viejo y los descartes intencionales.
Mantén observabilidad comparable. Usa el id del proxy en logs, auditorías, colas e informes. Compara resultados de negocio, no texto de logs. Operaciones necesita saber si el pedido 1042 se aceptó una vez y si salió su notificación.
Ensaya restauración y recuperación. Restaura datos y configuración en aislamiento, reproduce tráfico aceptado y confirma que las tareas quedan pausadas hasta activación manual. Así aparecen secretos, archivos locales, extensiones y orden de arranque ocultos. Un backup nunca restaurado es una promesa.
Prueba el reemplazo con el mismo reloj y configuración regional que producción. Cierres mensuales, cambios horarios, zonas SQL, valores JVM y números locales pueden escapar a replays normales. Fija zona y reloj e incluye casos grabados en los límites. Una fecha igual en HTML puede seleccionar otras filas o retrasar una tarea una hora.
Asigna dueño y condición de retirada a cada capa de compatibilidad. Traductores de cookies, adaptadores query, normalizadores y lectores de dos esquemas ayudan durante el cambio, pero se vuelven infraestructura permanente. Registra cada puente con dependencia antigua, prueba necesaria y última etapa permitida. Elimínalo cuando la ruta ya no necesite comportamiento CFML. Su retirada forma parte de la aceptación, con revisor y prueba productiva.
Conserva decisiones sobre excepciones y conversiones y enseña al equipo de guardia los límites nuevos. Un incidente futuro debe llevar a un servicio, query, tarea o runbook actual, no a buscar quién recuerda un include.
Retirar ColdFusion solo al acabar el trabajo oculto
Cero tráfico web no significa cero uso. Revisa historial del scheduler, firewall, rutas, cuentas, sesiones SQL, archivos, correo, monitorización, backups y favoritos administrativos. Busca hosts e IP directos en otros repositorios y manuales. Mantén un periodo de rechazo observado donde las llamadas inesperadas fallen de forma visible.
Retira autoridad por etapas. Desactiva tareas, escrituras y conectores, saca el nodo del proxy y observa. Archiva, cuando esté permitido, fuente, configuración, despliegue, informes, licencias y mappings finales. Conserva explicación histórica sin mantener un riesgo ejecutable.
El reemplazo ya no debe modelar conceptos CFML sin significado comercial. Servicios Go pueden poseer petición y dominio, TypeScript la interacción y Postgres las restricciones. La modernización ocurre tras medir paridad, pero antes de que las viejas abstracciones se endurezcan en el código. La transliteración solo cambia la factura.
Una reescritura ColdFusion de CodeHero se entrega en menos de 30 días y cambia la arquitectura en vez de copiar etiquetas. La fecha importa porque propiedad de rutas, tráfico, efectos y diferencias aceptadas muestran por qué puede retirarse el servidor.
El apagado final debe resultar aburrido. Ninguna ruta, tarea, integración u operador debería notarlo. Si parece un acto valiente, faltan inventario o pruebas.
Preguntas frecuentes
¿ColdFusion dejará de funcionar si no renovamos la licencia?
No supongas ni apagado ni continuidad. Comprueba versión, contrato, compra, activación y soporte, porque Adobe ha usado modelos distintos. Prueba un clon aislado mientras compras o asesoría confirma los derechos.
¿Debemos pasar primero de Adobe ColdFusion a Lucee?
Un runtime CFML compatible puede reducir la presión, pero no elimina la arquitectura ni garantiza identidad. Trata el cambio de runtime como una migración propia con pruebas de paridad.
¿Podemos traducir etiquetas CFML directamente a TypeScript?
La traducción mecánica conserva responsabilidades mezcladas y omite ciclo de vida, queries, sesiones y serialización. Define primero contrato de ruta y datos. Traduce la intención, no la sintaxis.
¿Qué se migra primero en una aplicación ColdFusion?
Empieza por inventario y ciclo Application.cfc, después tareas estrechas o endpoints de lectura medibles. Las páginas concurridas llegan cuando despliegue, observabilidad, adaptador y rollback ya funcionan.
¿Cómo reemplazamos los objetos query de ColdFusion?
No construyas una imitación universal salvo compatibilidad temporal. Devuelve registros explícitos y prueba columnas, null, precisión, orden, claves, errores y transacciones en el adaptador.
¿Pueden servir tráfico a la vez ambas aplicaciones?
Sí, si un proxy asigna rutas o grupos y sesión y datos son compatibles. Mantén un escritor por familia. Repartir escrituras con estado al azar provoca duplicados y redirecciones rotas.
¿Cómo probamos la paridad de una reescritura?
Reproduce tráfico protegido y compara estado, headers, cuerpo normalizado, datos y efectos. Revisa cada normalizador y diferencia. Archivos convertidos y unit tests no prueban el comportamiento real.
¿Conviene rediseñar la interfaz durante la migración?
Normalmente no si manda la licencia. Un rediseño cambia recorridos y aceptación mientras se mueve el runtime. Conserva primero el recorrido y rediseña tras asumir producción.
¿Cómo manejamos sesiones ColdFusion durante el cambio?
Elige store compatible, traducción en proxy o reautenticación controlada. Prueba vencimiento, rotación, serialización, cifrado, mensajes y formularios activos. No dejes que cada ruta improvise.
¿Cuándo es seguro apagar el servidor ColdFusion?
Cuando rutas, tareas, integraciones, sesiones SQL, archivos y operación no muestren dependencia. Retira autoridad por etapas y observa fallos antes de apagar. Guarda pruebas y configuración histórica.