¿Hasta cuándo se puede usar MSMQ? — La decisión de migración de una cola legacy que «ni siquiera está en desuso»

· Actualizado el: · · Windows, .NET, C#, MSMQ, Cola de mensajes, Tecnología legacy, Migración, Sistemas de información

«Este sistema usa MSMQ, pero he oído que se ha discontinuado. ¿Hay que migrarlo cuanto antes?» — esta es una pregunta que llevo escuchando repetidamente desde hace un año en las consultas de migración de sistemas legacy.

La respuesta tiene un poco de trampa. MSMQ (Microsoft Message Queuing) no solo no ha sido discontinuado: ni siquiera está declarado oficialmente en desuso. A fecha de julio de 2026, el nombre de MSMQ no aparece en la lista de funciones en desuso de Microsoft, y sigue incluido como función opcional en las versiones actuales de Windows. Y sin embargo, la sensación sobre el terreno de que es «una tecnología acabada» existe porque la API administrada oficial del lado de .NET está cerrada. La biblioteca estándar para manejar MSMQ, System.Messaging, solo existe en .NET Framework y nunca se portó a .NET (Core en adelante).

En otras palabras, MSMQ no es una tecnología que «se detendrá mañana», sino una tecnología que se convierte en un muro en el momento en que se intenta subir la aplicación a .NET.

El público objetivo de este artículo son los desarrolladores encargados del mantenimiento y la migración de sistemas existentes que usan MSMQ, y el personal de los departamentos de sistemas de información al que se le pide esa decisión. El objetivo es que, tras verificar la veracidad del rumor de que «parece que se ha discontinuado», usted pueda decidir si migrar o no según las condiciones concretas de su propio entorno.

En este artículo separamos el rumor de los hechos y ordenamos la decisión entre seguir usándolo o migrar, así como la forma de elegir el destino de la migración. La migración en sí desde VB6 o .NET Framework ya se trata en «La migración práctica de VB6 a .NET» y en «Lista de verificación previa a la migración de .NET Framework a .NET», así que este artículo se centra únicamente en la parte de la cola.

1. Antes que nada, la conclusión

  • MSMQ no está declarado oficialmente en desuso. No figura ni en la lista de funciones en desuso de los clientes Windows ni en la lista de funciones eliminadas o cuyo desarrollo ha finalizado de Windows Server (a fecha de julio de 2026).12
  • Sin embargo, no existe una API administrada oficial de .NET. System.Messaging solo cubre .NET Framework 1.1 a 4.8.1,3 y tampoco está incluida en el paquete de compatibilidad de Windows, el recurso de compatibilidad para la migración a .NET.4 Queda la vía de llamar a la API nativa Win32 mediante P/Invoke, pero se sitúa como un medio de prórroga (capítulo 3).
  • Existe un port con CoreWCF, pero se limita a la migración de servicios WCF invocados a través de una cola (el lado receptor), y es una vía que hay que usar tras verificar sus condiciones. CoreWCF en sí cuenta con una política de soporte de Microsoft, pero la implementación del transporte MSMQ (CoreWCF.MSMQ) depende de un port comunitario de System.Messaging para .NET Framework.5
  • El eje de la decisión es «si se va a subir la aplicación a .NET o no». Si se sube, la norma es migrar también la cola (existen vías de prórroga con P/Invoke o CoreWCF, pero eso implica asumir la decisión de cargar con el mantenimiento). Si no se sube (dejarlo congelado), se puede planear seguir funcionando mientras .NET Framework 4.8 reciba soporte como componente del sistema operativo.6
  • El primer candidato como destino de migración no es un bróker de mensajes, sino una cola de tabla de la base de datos. La consistencia que protegía MSMQ combinado con transacciones distribuidas (DTC) se sustituye de forma más directa con una cola de tabla que se puede procesar en la misma transacción que la base de datos de negocio (capítulo 5).
  • Haga primero un inventario del formato de los mensajes. La serialización basada en BinaryFormatter se eliminó del runtime en .NET 9,7 y si mantiene el formato antiguo mientras conviven el sistema viejo y el nuevo, se quedará atascado (capítulo 6).

2. MSMQ en 30 segundos

MSMQ es la infraestructura de colas de mensajes que ha venido incluida con Windows. Una aplicación escribe mensajes en la cola, y otra aplicación (ya sea en la misma máquina o en otra distinta) los extrae cuando le conviene. Sus características se resumen en estos tres puntos.

  • Store-and-forward: aunque el destino esté caído, el mensaje se acumula localmente y llega una vez que este se recupera. Es robusto frente a enlaces inestables entre sedes. Sin embargo, esta persistencia no es incondicional: el mensaje rápido (express) predeterminado puede quedarse en memoria, y se pierde si se reinicia el servicio MSMQ o la máquina. Lo que se persiste en disco son los mensajes en los que el emisor especificó Recoverable (recuperable), o los mensajes transaccionales.
  • Transacciones: las operaciones sobre la cola se pueden convertir en transacciones, y combinándolas con MS DTC (Coordinador de transacciones distribuidas) se puede confirmar en una sola transacción distribuida tanto la «extracción de la cola» como la «actualización de la base de datos».
  • Incluido en el sistema operativo: al poder usarse sin instalar middleware adicional, fue ampliamente adoptado en los sistemas de negocio de la década de 2000, especialmente en la integración de datos de pedidos, el procesamiento asíncrono de informes y la coordinación entre procesos en plantas de fabricación.

Precisamente porque esta combinación de «incluido en el SO, con transacciones y resistente a estar offline» era excelente, sigue en uso activo hoy en día. Al pensar en el destino de la migración, el eje de la decisión también es cuál de estos tres puntos se está usando realmente.

Conjunto mínimo de términos usados en este artículo

La tabla de decisión del capítulo 5 y el inventario del capítulo 6 dan por sentados los siguientes términos. Repáselos aquí de una vez.8

  • Cola privada — una cola que no se publica en el servicio de directorio (Active Directory) y que solo se registra en ese equipo. Se especifica con un formato como .\private$\nombre_de_cola. En cambio, la cola pública se registra en el servicio de directorio y se puede buscar dentro del dominio. En los sistemas de negocio de tamaño pequeño o mediano, casi siempre se usan colas privadas.
  • Mensaje express — el modo de envío predeterminado. Es rápido porque se mantiene en memoria tanto durante como después de la entrega, pero se pierde si se detiene el servicio MSMQ o la máquina.
  • Mensaje recoverable (recuperable) — un modo en el que se escribe en disco tanto en el equipo emisor como en cada equipo intermedio, y se conserva en disco también en la cola de destino. Sobrevive a los reinicios. Lo especifica explícitamente el emisor.
  • Cola transaccional — una cola que solo maneja mensajes transaccionales. Se determina al crear la cola y no se puede cambiar después (esto es relevante para el procedimiento de migración del capítulo 6).
  • DTC (Coordinador de transacciones distribuidas) — un servicio de Windows que coordina transacciones que abarcan varios recursos (por ejemplo, una cola de MSMQ y una base de datos). Es el mecanismo que permite confirmar como una sola unidad la «extracción de la cola» y la «actualización de la BD», y se convierte en el punto más disputado de la decisión de migración del capítulo 5.
  • Cola de diario (journal) / cola de mensajes no entregados (dead-letter) — colas de sistema que MSMQ genera automáticamente. La cola de diario acumula una «copia de los mensajes enviados o extraídos», y la cola de mensajes no entregados acumula los «mensajes que no se pudieron entregar». Si se dejan sin atender, consumen espacio, por lo que en una operación congelada deben monitorizarse (capítulo 7).

3. Los hechos — «discontinuado» no es la palabra exacta

La pregunta «¿se puede usar MSMQ?» genera confusión porque la respuesta cambia según la capa, pero se habla de ella como si fuera una sola cosa. Antes que nada, resumamos el panorama general en una sola tabla.

Capa Estado actual Significado práctico
Función del SO (función opcional de Windows) Sigue existiendo. Está incluida en los clientes Windows/Server actuales y no se ha emitido ninguna declaración de desuso12 Si se activa, sigue funcionando hoy. Se puede seguir usando mientras dure el periodo de soporte del SO
API nativa Win32 (MQSendMessage, etc.) Documentada y disponible9 Queda la vía de llamarla desde .NET mediante P/Invoke. Pero los formateadores y la integración transaccional habrá que escribirlos y mantenerlos uno mismo
System.Messaging de .NET Framework Disponible. Pero solo cubre .NET Framework 1.1 a 4.8.13 Los sistemas existentes funcionan sobre esto. No hay continuidad más allá
API administrada oficial de .NET (Core en adelante) No existe. Tampoco está incluida en el paquete de compatibilidad de Windows4 En el momento de subir la aplicación a .NET, hay que rehacer la parte de la cola
Enlace MSMQ de WCF → CoreWCF.MSMQ Existe un port impulsado por la comunidad. CoreWCF en sí tiene una política de soporte, pero la implementación de MSMQ depende de un port comunitario de System.Messaging5 Sirve para prolongar la vida de los servicios WCF invocados a través de una cola (el lado receptor), pero no sustituye al lado emisor ni es una API de cola genérica
Adopción en proyectos nuevos No se recomienda Porque no existe una vía oficial de futuro

A continuación, verificamos por orden el fundamento de cada fila de esta tabla.

En primer lugar, MSMQ no figura en la lista de funciones en desuso. Si se consulta la lista «Deprecated features» de los clientes Windows, aparecen NTLM, VBScript o WordPad, pero no hay ninguna entrada para MSMQ.1 En la lista «Features Removed or No Longer Developed» del lado de Windows Server tampoco se menciona MSMQ, ni siquiera en la pestaña de Windows Server 2025.2 El desuso (deprecated) es una declaración oficial de que «se ha dejado de desarrollar activamente», y la situación actual es que ni siquiera se ha emitido esa declaración.

En segundo lugar, System.Messaging se ha quedado detenido en .NET Framework. La versión objetivo de la referencia va de .NET Framework 1.1 a 4.8.1, y no existe una versión para .NET (Core en adelante).3 El paquete de compatibilidad de Windows (Microsoft.Windows.Compatibility), que sirve de receptor para las API exclusivas de .NET Framework, ofrece unas 20.000 API que cubren el registro, WMI, los servicios de Windows, EventLog, etc., pero su lista de áreas tecnológicas no incluye la mensajería (System.Messaging).4 Dicho con precisión, lo que está cerrado es la API administrada. La API nativa Win32 de MSMQ (MQSendMessage, MQReceiveMessage, etc.) sigue documentada hoy en día, y en sí es posible llamarla desde .NET mediante P/Invoke. Sin embargo, esto implica escribir como wrapper propio, y seguir manteniendo, los formateadores y la integración transaccional que System.Messaging absorbía, por lo que su lugar no es el de «la opción principal para seguir usándolo», sino el de «un medio de prórroga para cuando, pase lo que pase, hay que conservarlo».

En tercer lugar, la integración de MSMQ con WCF está dentro del mismo muro. El WCF de .NET Framework tenía un enlace (binding) que usaba MSMQ como capa subyacente, pero si se intenta reproducir esta vía en .NET moderno, se llega a CoreWCF, un proyecto impulsado por la comunidad. CoreWCF publica un paquete compatible con MSMQ (CoreWCF.MSMQ) como parte de sus transportes de tipo cola, pero su implementación declara explícitamente que depende de un port comunitario de la biblioteca System.Messaging para .NET Framework.5 En cuanto a si funciona, funciona, y como CoreWCF en sí cuenta con una política de soporte oficial de Microsoft, tampoco se trata de «una biblioteca completamente no oficial».5 Sin embargo, si el port comunitario de System.Messaging del que depende el transporte MSMQ recibe el mismo trato es harina de otro costal. Si decide adoptarlo, verifique si la versión que va a usar está cubierta por la política de soporte y cómo se trata esta dependencia antes de decidir.

Estos son los fundamentos de cada fila de la tabla resumen del principio. No es que «MSMQ se haya discontinuado», sino que «no existe una vía oficial desde .NET moderno hasta MSMQ» — si mantiene esta distinción presente, los debates internos de su empresa dejarán de ir por caminos separados.

4. La verdadera cara de «funciona, pero es un problema»

Las consultas sobre sistemas que involucran MSMQ casi siempre empiezan no por un incidente, sino por una estimación de migración. El verdadero problema no es MSMQ en sí, sino que MSMQ se convierte en un ancla que ata toda la aplicación a .NET Framework.

.NET Framework 4.8 se trata como un componente de Windows y recibe soporte siguiendo el ciclo de vida del sistema operativo en el que está instalado.6 Por eso, a la pregunta de «¿seguirá funcionando?» se puede responder «por el momento, seguirá funcionando». Aun así, los siguientes puntos se van agravando con toda seguridad conforme pasa el tiempo.

  • No se puede contratar ni traspasar el conocimiento a nadie. Cada año hay menos técnicos capaces de explicar System.Messaging y DTC. Es un ejemplo típico de la situación que describimos en «El mantenimiento de sistemas sin código fuente ni documentación».
  • No se pueden aprovechar las mejoras del runtime ni de las bibliotecas nuevas. Muchas de las nuevas construcciones de sintaxis de C# se pueden usar en .NET Framework con solo actualizar el compilador, pero no se pueden usar las mejoras de rendimiento del runtime ni las nuevas bibliotecas estándar, y cada vez es más difícil elegir los paquetes recientes que van dejando de dar soporte a .NET Framework.
  • La transacción distribuida se convierte en el mayor obstáculo de la migración. El diseño de MSMQ+DTC, que hace atómica la «extracción de la cola y la actualización de la BD», no se puede reproducir en los servicios de cola en la nube. Si se deja esto sin resolver y solo se convierte a .NET el resto, al final queda el núcleo más duro.
  • La bomba de tiempo del formato de serialización. El cuerpo de los mensajes de los sistemas antiguos a veces está en serialización binaria, y BinaryFormatter se eliminó del runtime en .NET 9.7 Al migrar, hay que revisar también el formato de los mensajes.

En definitiva, la respuesta práctica a la pregunta «¿hasta cuándo se puede usar MSMQ?» es: «funcionará mientras el SO le dé soporte, pero la dificultad de la migración aumenta cuanto más se espera». Incluso si decide postergar la decisión, al menos debería tener claro de antemano «dónde están los puntos difíciles» con la tabla de decisión del próximo capítulo. </content>

5. Tabla de decisión para el destino de la migración

El destino de la migración no se elige preguntando «¿cuál es el producto sucesor de MSMQ?», sino según qué propiedad se está usando realmente.

5.1. Primero, reducir los requisitos a cuatro preguntas

  1. ¿El destino de la cola (el procesamiento del lado receptor) es un proceso que actualiza la base de datos de la propia empresa?
  2. ¿Se está usando una transacción distribuida (DTC)? (cola transaccional + actualización de la BD)
  3. ¿El emisor y el receptor están en máquinas o sedes distintas? ¿Se está usando realmente la resistencia a estar offline (store-and-forward)?
  4. ¿Cuál es el volumen real de mensajes? (en muchos sistemas de negocio son de unos pocos miles a decenas de miles al día, un volumen que cualquiera de las opciones maneja sin problema)

5.2. Tabla de decisión

Propiedad que se está usando Primer candidato Motivo y advertencias
Procesamiento asíncrono dentro del mismo sistema (el lado receptor actualiza la BD) Cola de tabla de la BD Se puede confirmar la «extracción del mensaje» y la «actualización de los datos de negocio» en la misma transacción local, eliminando la necesidad de DTC. Se puede seguir usando tal cual la copia de seguridad, el monitoreo y la operación existentes. Además, el emisor también puede poner en la misma transacción la «actualización de los datos de negocio y la inserción de la fila del mensaje»; esto es el llamado patrón Outbox
Se hacen atómicas la cola y la actualización de la BD mediante DTC Cola de tabla de la BD La esencia de la migración es sustituir la transacción distribuida por una transacción local. Como las colas en la nube no pueden participar en DTC, mientras exista este requisito, las opciones basadas en bróker suponen un rodeo
Integración débilmente acoplada entre varios sistemas y lenguajes RabbitMQ (on-premise) / Azure Service Bus (también en la nube) La difusión (fan-out) y el enrutamiento de la entrega son el punto fuerte de un bróker. Con RabbitMQ hay que presupuestar la carga de operarlo uno mismo (redundancia, actualizaciones)
Resistencia a estar offline entre sedes (store-and-forward) Azure Service Bus u otro servicio equivalente + diseño de reenvío, o cola de tabla en la sede + sincronización Hay pocos mecanismos que sustituyan de forma transparente el «acumular localmente en el emisor y entregar más tarde» de MSMQ. Hay que cambiar a un diseño en el que la aplicación asuma explícitamente la responsabilidad de acumular en el lado emisor
Productor/consumidor dentro del mismo proceso Una cola en memoria como Channels de .NET Un caso en el que, para empezar, no hacía falta una cola entre procesos. Que quede resuelto dentro del proceso, y si se necesita persistencia, pasar a una cola de tabla
Se usa únicamente como comunicación entre procesos (IPC) entre servicios de Windows IPC como los named pipes Pero solo se puede sustituir cuando ambas partes están siempre activas al mismo tiempo. Mientras el receptor está detenido, MSMQ sigue aceptando envíos (incluso como mensajes express) y los entrega más tarde, pero una tubería (pipe) falla de inmediato. Si depende de la acumulación durante las paradas, implemente el reenvío y el búfer en la aplicación, o conserve la cola. Para elegir, consulte «Tabla de decisión de IPC en Windows»

5.3. Implementación mínima de una cola de tabla

Muchas personas dicen que la expresión «cola de tabla» no les resulta intuitiva, así que mostramos su forma mínima. Primero, la definición de la tabla (SQL Server).

CREATE TABLE dbo.JobQueue (
    Id          BIGINT IDENTITY(1,1) PRIMARY KEY,
    Payload     NVARCHAR(MAX) NOT NULL,                    -- Cuerpo. Se guarda como JSON
    Status      TINYINT       NOT NULL DEFAULT 0,          -- 0: sin procesar 1: en proceso 2: completado
    EnqueuedAt  DATETIME2     NOT NULL DEFAULT SYSUTCDATETIME(),
    StartedAt   DATETIME2     NULL,                        -- Se usa para recuperar filas que quedaron en proceso tras una caída
    RetryCount  INT           NOT NULL DEFAULT 0
);
CREATE INDEX IX_JobQueue_Status ON dbo.JobQueue (Status, Id);

La extracción marca una sola fila como «en proceso» mientras recibe el cuerpo del mensaje. Al añadir READPAST, se puede saltar sin esperar las filas que otros workers tienen bloqueadas (se puede ejecutar simultáneamente desde varios procesos).

WITH next_job AS (
    SELECT TOP (1) *
    -- READCOMMITTEDLOCK es necesario en bases de datos con READ_COMMITTED_SNAPSHOT en ON (se explica más abajo).
    -- En bases de datos con OFF equivale al comportamiento predeterminado, así que dejarlo puesto funciona en ambos casos
    FROM   dbo.JobQueue WITH (READPAST, UPDLOCK, READCOMMITTEDLOCK)
    WHERE  Status = 0
    ORDER  BY Id          -- Se extrae en el orden de inserción. Esta es la condición para que sea una «cola»
)
UPDATE next_job
SET    Status = 1, StartedAt = SYSUTCDATETIME()
OUTPUT inserted.Id, inserted.Payload;

READPAST no se puede usar tal cual en una base de datos con READ_COMMITTED_SNAPSHOT en ON. La documentación oficial indica explícitamente que «cuando READ_COMMITTED_SNAPSHOT está en ON y el nivel de aislamiento de la sesión es READ COMMITTED (o se usa además la sugerencia READCOMMITTED), no se puede especificar READPAST», y como solución en ese caso propone añadir también la sugerencia READCOMMITTEDLOCK.10 Como el nivel de aislamiento predeterminado es READ COMMITTED, en una base de datos donde simplemente se ha activado READ_COMMITTED_SNAPSHOT, esta extracción no solo deja de «saltar las filas de otros workers», sino que la propia sentencia da error. Azure SQL Database lo tiene en ON de forma predeterminada, y tampoco es raro encontrarlo activado en entornos on-premise como medida contra el bloqueo en las lecturas. Verifique de antemano cuál es el caso de la base de datos de destino.

SELECT is_read_committed_snapshot_on FROM sys.databases WHERE name = DB_NAME();

El motivo por el que se omite ROWLOCK del habitual WITH (READPAST, UPDLOCK, ROWLOCK) es que ROWLOCK y READCOMMITTEDLOCK pertenecen al mismo grupo de «sugerencias de granularidad», y no se pueden especificar ambas sobre una misma tabla.10 Como READPAST solo puede saltar bloqueos de fila, no de página, sería deseable indicar ROWLOCK de forma explícita, pero en la práctica no se produce escalada de bloqueo para la única fila que se obtiene con la búsqueda por índice de TOP (1). Si sabe con certeza que READ_COMMITTED_SNAPSHOT está en OFF y quiere indicar ROWLOCK explícitamente, quite en su lugar READCOMMITTEDLOCK.

Si se omite ORDER BY y se escribe UPDATE TOP (1), qué fila se selecciona queda indeterminado. Está documentado oficialmente que el TOP de UPDATE no ordena las filas objetivo, y ni siquiera con un índice en (Status, Id) se garantiza el orden de extracción.11 En integraciones que dan por supuesto que se procesa en el orden de inserción, esto se convierte en un defecto en el que los trabajos antiguos se quedan postergados indefinidamente.

Sin embargo, lo que ORDER BY Id garantiza es únicamente el orden de extracción. El orden en que termina el procesamiento no queda garantizado. Como READPAST sirve para «saltar las filas que otros workers tienen bloqueadas», mientras el worker A toma el trabajo 1 y tarda mucho en procesarlo, el worker B puede tomar el trabajo 2 y confirmarlo (commit) antes.

Lo que queda garantizado Lo que no queda garantizado
Qué fila se extrae primero (ORDER BY Id) Qué fila se refleja primero en los datos de negocio

En integraciones donde el orden en que se aplican los cambios importa, como cuando resulta problemático que se invierta el orden de las actualizaciones sobre el mismo número de pedido, esto no es suficiente. Las formas que se pueden adoptar son estas dos:

  • Usar un único consumidor. Se renuncia al paralelismo a cambio de garantizar el orden. Si el rendimiento (throughput) es suficiente, esta es la forma más simple y menos propensa a romperse
  • Dividir por clave. Se fija el worker según una clave, como el número de pedido, o se añade a la extracción la condición de «no extraer si ya hay una fila con la misma clave en proceso», de modo que el orden solo se garantiza dentro de cada clave. Se renuncia al orden entre claves distintas

Si no se adopta ninguna de las dos, deje constancia explícita en el diseño de la migración de que en cuanto se ejecuta en paralelo, no existe un FIFO global. Esto se pasa por alto especialmente al migrar desde MSMQ. Con las colas de MSMQ ocurre lo mismo si se reciben en paralelo, pero si se migra con el entendimiento de que «es una cola, así que va en orden», da la impresión de que el problema de orden aparece justo al pasar a una cola de tabla.

El worker del lado receptor solo tiene que ejecutar esto dentro de la misma transacción local que el procesamiento de negocio (C#, pseudocódigo).

while (!stoppingToken.IsCancellationRequested)
{
    using var tx = connection.BeginTransaction();

    var job = DequeueOne(connection, tx);          // El UPDATE ... OUTPUT de arriba
    if (job is null)
    {
        tx.Commit();
        await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);  // Si está vacío, esperar solo el intervalo de sondeo (polling)
        continue;
    }

    ApplyBusinessData(connection, tx, job);        // ← Actualización de los datos de negocio (el trabajo que realmente se quiere hacer)
    MarkDone(connection, tx, job.Id);              // Status = 2

    tx.Commit();   // La "extracción" y la "actualización de negocio" se confirman a la vez en esta línea
}

Este es el punto en el que se sustituye MSMQ+DTC. En MSMQ, la «extracción de la cola» y la «actualización de la BD» eran recursos distintos, por lo que se necesitaba una transacción distribuida (DTC) para unificar ambas. Si la cola es una tabla de la BD, ambas son actualizaciones sobre la misma base de datos, así que basta con una transacción local normal. Si se introduce RabbitMQ o Azure Service Bus, se pierde esta propiedad (la cola y la BD vuelven a ser recursos distintos), y hay que construir la idempotencia y el reenvío en el lado de la aplicación.

Para la operación real, hace falta añadir aproximadamente estas tres cosas.

  • Recuperación de filas que quedaron en proceso tras una caída. Incluya en una ejecución periódica un proceso de recuperación que devuelva a Status = 0 las filas con Status = 1 cuyo StartedAt sea más antiguo que un tiempo determinado.
  • Límite de reintentos y desvío. Las filas cuyo RetryCount supere el límite se mueven a otra tabla (o a Status = 9). Es el lugar equivalente a la cola de mensajes no entregados de MSMQ.
  • Limpieza de las filas completadas. Elimine o archive periódicamente las filas con Status = 2. Si se deja así, la tabla crece y la eficacia del índice se degrada.

En el lado emisor, ponga en la misma transacción la actualización de los datos de negocio y el INSERT de la fila del mensaje (patrón Outbox). Con esto desaparece también la inconsistencia de que «los datos de negocio se actualizaron pero el mensaje no salió».

Lo que queremos destacar es que en los sistemas de negocio de tamaño pequeño o mediano, la cola de tabla suele ser el primer candidato. Los artículos comparativos de productos de cola de mensajes tienden a plantearse como «RabbitMQ vs. Kafka vs. Service Bus», pero lo que las aplicaciones de la generación MSMQ suelen poner en la cola es, en la mayoría de los casos, un «trabajo asíncrono que actualiza la misma BD», y eso se puede lograr de forma suficiente, y además más simple, con una tabla de la BD y sondeo (polling) (o notificaciones). El coste operativo de añadir un middleware nuevo (monitoreo, redundancia, parches, formación del personal) pesa especialmente en las estructuras de tamaño pequeño o mediano.

6. Procedimiento práctico de migración

El procedimiento sigue la fórmula clásica de la migración de sistemas legacy: «observar antes de mover».

  1. Inventario de dependencias. Localice en el código las referencias a System.Messaging y los puntos donde se crean objetos MessageQueue. Busque también, en los archivos de configuración de WCF, netMsmqBinding / msmqIntegrationBinding, así como las llamadas a la API nativa (funciones MQ* como MQSendMessage) o a través de COM. Puede haber vías que dependan de MSMQ aunque no se referencie System.Messaging. Los puntos a verificar son: (a) la ruta de la cola (local o remota, privada o pública), (b) si es una cola transaccional o si los mensajes se marcan como Recoverable (si no es ninguna de las dos cosas, el sistema actual funciona bajo el supuesto de que los mensajes se pierden al reiniciar), (c) el formateador (XmlMessageFormatter / BinaryMessageFormatter / ActiveXMessageFormatter), (d) el uso de la cola de diario y de la cola de mensajes no entregados, y (e) quién crea y elimina la cola (el instalador o la propia aplicación).

    Con solo verificar el inventario no se aporta nada a la decisión de migración. Rellene una fila por cada cola con el siguiente formato, y utilícelo directamente como fundamento de la política de migración (se puede usar tal cual como anexo del documento de aprobación interna).

    Punto Dónde mirar Qué registrar Cómo influye en la decisión
    (a) Ruta de la cola La cadena de ruta pasada a MessageQueue, el destino de conexión en el archivo de configuración, la especificación FormatName: Si es local o remota, si es privada o pública, el nombre de la máquina de destino Si es remota o entre sedes, determina si hace falta store-and-forward (fila «resistencia offline» de 5.2). Si es local y autocontenida, cae en la primera fila de 5.2
    (b) Transacciones y Recoverable El punto donde se crea la cola (si es transaccional), si se especifica Recoverable al enviar, si se usa DTC Si es cola transaccional o no, si se especifica Recoverable, si participa en DTC Si hay DTC, el destino casi con seguridad es una cola de tabla. Si no hay ninguna de las dos cosas, deje constancia de que el sistema actual opera bajo el supuesto de que los mensajes se pierden al reiniciar
    (c) Formateador Los puntos donde se especifica XmlMessageFormatter / BinaryMessageFormatter / ActiveXMessageFormatter El formateador usado y el tipo del cuerpo del mensaje Si es de la familia BinaryFormatter, es obligatorio pasar a JSON (paso 2). Es el principal factor del esfuerzo de migración7
    (d) Cola de diario y de mensajes no entregados Las propiedades de la cola (si el diario está habilitado), el contenido de las colas de sistema, el manual de operación Si se usa el diario, si realmente se revisa la cola de mensajes no entregados «Cómo se tratan los mensajes fallidos» se convierte en un requisito de diseño del destino (en una cola de tabla, la tabla de desvío)
    (e) Quién la crea y la elimina El instalador, los scripts de despliegue, la llamada a Create al iniciar la aplicación Quién la crea y quién configura los permisos En la migración, «quién prepara la cola nueva» se sustituye directamente por esto. Si se opta por dejarlo congelado, trasládelo al procedimiento de preparación de equipos (capítulo 7)
  2. Decidir el formato de los mensajes. Establezca JSON como formato predeterminado tras la migración. Lo que no se puede llevar es la serialización de la familia BinaryFormatter, como BinaryMessageFormatter. BinaryFormatter ya se eliminó en .NET 9 y tampoco se recomienda por motivos de seguridad.7 Por otro lado, si se usa un formato binario cuya especificación se mantiene de forma independiente, como Protocol Buffers o MessagePack, no hay problema en llevar ese formato tal cual al sistema nuevo.
  3. Migrar empezando por el lado receptor. Prepare primero la cola nueva (por ejemplo, una cola de tabla), adapte el procesamiento del lado receptor a la cola nueva y solo después cambie el lado emisor. Durante el periodo de migración, intercalar un pequeño puente (bridge) que traslade los mensajes de la antigua MSMQ a la cola nueva (este puede seguir en .NET Framework) evita tener que cambiar el lado emisor de golpe. Sin embargo, si el puente se cae entre la «extracción desde MSMQ» y la «escritura en la cola nueva», se pierden mensajes o se duplican. Si el origen es una cola transaccional, la condición mínima es configurar la recepción de MSMQ como transaccional para poder revertirla si falla la escritura, y diseñar el lado de la cola nueva para que sea idempotente, descartando duplicados por el ID del mensaje. Si el origen es una cola no transaccional, este recurso no se puede usar, porque el atributo transaccional de la cola se fija al crearla y no se puede cambiar después. En ese caso, hay que montarlo en el orden «leer con Peek → escribir de forma idempotente en la cola nueva → confirmar que se escribió y solo entonces retirarlo de MSMQ» (aunque se caiga antes de retirarlo, la idempotencia del lado de la cola nueva absorbe la duplicación). Si construir cualquiera de las dos soluciones no está justificado para el tamaño del proyecto, es más seguro prescindir del puente y recurrir directamente al paso 5, «vaciar y cambiar».
  4. Fijar el comportamiento antes de reescribir. El procesamiento de colas es un área propensa a errores dependientes de la sincronización (timing). Si antes de la migración prepara pruebas de caracterización del tipo «con este mensaje de entrada, este resultado», la verificación tras la sustitución se vuelve mecánica (véase «Fijar el comportamiento con pruebas de caracterización antes de refactorizar»).
  5. Cambiar con la cola vacía. Cambiar con mensajes aún pendientes es el caldo de cultivo del procesamiento duplicado y de las pérdidas. Vaciar por completo la cola durante una parada planificada y luego cambiar es, al final, el método más seguro y rápido.

7. Condiciones mínimas para optar por dejarlo congelado

La decisión de «no tener un plan para subir la aplicación a .NET y, por relación coste-beneficio, no migrar por el momento» es racional de forma condicional. A continuación presentamos, en forma de lista de verificación que se puede trasladar tal cual a los documentos de aprobación interna o de revisión, las condiciones mínimas para ese caso. Considere que dejarlo congelado solo se convierte en una opción cuando se han marcado las cuatro casillas.

Verificación Condición mínima Qué hacer en concreto Qué ocurre si no se cumple
Indicar MSMQ explícitamente en el procedimiento de preparación y restauración de equipos MSMQ es una función opcional de Windows. Anote en el manual de configuración del entorno el procedimiento de activación mediante «Activar o desactivar las características de Windows» o mediante DISM/PowerShell Al sustituir un PC o un servidor se olvida activarla, y el día de la migración no funciona sin causa aparente
Monitorizar la longitud de la cola Configure el monitoreo con umbral del número de mensajes acumulados y las notificaciones correspondientes. Incluya también la cola de mensajes no entregados y la cola de diario Aunque el receptor se detenga no se genera ningún error y los mensajes se siguen acumulando, de modo que el negocio se detiene sin que nadie se dé cuenta
Documentar la configuración Registre la ruta de la cola, los permisos, si hay transacciones, el formateador y la configuración del diario (se puede usar tal cual la tabla de inventario del capítulo 6) La futura estimación de migración tiene que rehacerse desde la investigación, empeorando tanto la precisión como el esfuerzo
Revisar la decisión una vez al año Verifique anualmente si «ha entrado en la lista de funciones en desuso» y si «el comportamiento ha cambiado con alguna actualización del sistema operativo» Se acaba actuando con prisas después de que se publique el anuncio de desuso

El cuarto punto tiende a subestimarse especialmente, pero es precisamente esta revisión anual la que permite no tener que actuar con prisas incluso después de que se publique un anuncio. A la inversa, dejarlo congelado en un entorno donde no se cumplen estos cuatro puntos equivale a «esperar a que se detenga sin verlo venir».

8. Resumen

  • A fecha de julio de 2026, MSMQ no está declarado oficialmente en desuso y sigue existiendo como función del sistema operativo. La percepción de que «ya se ha discontinuado» no es exacta.12
  • Por otro lado, System.Messaging se ha quedado exclusivo de .NET Framework, no está incluido en el paquete de compatibilidad, y no existe una vía oficial hacia .NET (Core en adelante). Aunque CoreWCF en sí cuenta con una política de soporte, su transporte MSMQ depende de un port comunitario de System.Messaging.345
  • El eje de la decisión es «si se sube la aplicación a .NET». Si se sube, la norma es migrar también la cola (prolongar la vida con P/Invoke u otras vías se paga con carga de mantenimiento); si se deja congelado, esto solo es viable con monitoreo y documentación como condición.6
  • El primer candidato como destino de migración es la cola de tabla de la BD. La esencia consiste en sustituir la consistencia de MSMQ+DTC por una transacción local; la introducción de un producto bróker se evalúa después.
  • La serialización de la familia BinaryFormatter no se puede llevar al sistema nuevo, ya que fue eliminada en .NET 9. Al migrar, establezca JSON como predeterminado, aunque los formatos que se mantienen de forma independiente, como protobuf, se pueden conservar tal cual.7
  • Cambiar en el orden receptor → puente → emisor, y fijar el comportamiento con pruebas de caracterización antes de reescribir, es la forma de proceder que evita incidentes.

Artículos relacionados

Áreas de consultoría relacionadas

KomuraSoft LLC se encarga del inventario y la planificación de migración de configuraciones legacy que incluyen MSMQ, de la migración de .NET Framework a .NET, y de la modificación de sistemas de negocio que incluyen procesamiento de colas.

Referencias

  1. Microsoft Learn, Deprecated features in the Windows client. Lista oficial de funciones para las que se ha finalizado el desarrollo activo (en desuso) en los clientes Windows. Sobre el hecho de que, en la lista a fecha de julio de 2026, figuran NTLM, VBScript, WordPad, etc., mientras que MSMQ (Microsoft Message Queuing) no aparece, y sobre que el desuso (deprecated) es una etapa en la que «no se desarrolla activamente y podría eliminarse en una actualización futura», que se distingue de la eliminación (removed).  2 3 4

  2. Microsoft Learn, Features Removed or No Longer Developed in Windows Server. Lista oficial de funciones eliminadas y funciones cuyo desarrollo ha finalizado (en desuso) en Windows Server. Sobre el hecho de que MSMQ no figura en la lista a fecha de julio de 2026, incluida la pestaña de Windows Server 2025, y sobre que los componentes en desuso siguen incluidos en Windows Server, reciben soporte para entornos de producción conforme al ciclo de vida del producto, y continúan recibiendo actualizaciones de seguridad y de calidad.  2 3 4

  3. Microsoft Learn, MessageQueue Class (System.Messaging). Sobre el hecho de que la referencia de la clase System.Messaging.MessageQueue cubre desde .NET Framework 1.1 hasta 4.8.1, y de que no existe una versión para .NET (Core en adelante).  2 3 4

  4. Microsoft Learn, Use the Windows Compatibility Pack to port code to .NET. Sobre el hecho de que el paquete de compatibilidad de Windows (paquete Microsoft.Windows.Compatibility) ofrece unas 20.000 API para cubrir la dependencia de las API exclusivas de .NET Framework al migrar a .NET, y de que su lista de áreas tecnológicas (CodeDom, configuración, Directory Services, Drawing, ODBC, ACL, WCF, registro, WMI, contadores de rendimiento, servicios de Windows, EventLog, etc.) no incluye la mensajería (System.Messaging).  2 3 4

  5. CoreWCF project, CoreWCF.MSMQ (NuGet) y CoreWCF 1.4.0 Preview release, Microsoft, CoreWCF Support Policy. Sobre el hecho de que CoreWCF es un proyecto impulsado por la comunidad que porta el lado servidor de WCF a .NET, y de que Microsoft ofrece una política de soporte oficial para él; de que se publica compatibilidad con MSMQ (paquete CoreWCF.MSMQ) como parte de sus transportes de tipo cola; y de que esa implementación de MSMQ depende de un port comunitario de la biblioteca System.Messaging para .NET Framework.  2 3 4 5

  6. Microsoft Learn, .NET Framework official support policy. Sobre el hecho de que .NET Framework 4.8 se define como un componente del sistema operativo Windows y recibe soporte conforme a la política de ciclo de vida del producto padre (el SO) en el que está instalado.  2 3

  7. Microsoft Learn, BinaryFormatter migration guide. Sobre el hecho de que BinaryFormatter se ha ido retirando de forma gradual por motivos de seguridad, de que a partir de .NET 9 su implementación se eliminó del runtime y no está disponible de forma predeterminada, y de que se recomiendan como destino formatos de serialización seguros como JSON (System.Text.Json).  2 3 4 5

  8. Microsoft Learn (archivo), Express and Recoverable Messaging, System-Generated Queues, Message Queuing (MSMQ). Sobre el hecho de que un mensaje express se mantiene en RAM tanto durante como después de la entrega, y se pierde si se detiene el equipo donde reside el mensaje o el servicio MSMQ; de que un mensaje recoverable se escribe en disco tanto en el equipo emisor como en cada equipo intermedio, y se conserva en disco también en la cola de destino; de que la cola pública se registra en el servicio de directorio mientras que la cola privada solo se registra en el equipo local y no se publica en el servicio de directorio; y de que la cola de diario, que conserva una copia de los mensajes extraídos de la cola o enviados, y la cola de mensajes no entregados (dead-letter), que conserva los mensajes que no se pudieron entregar, son colas de sistema generadas por MSMQ. 

  9. Microsoft Learn (archivo), Message Queuing Functions y MQSendMessage, MQReceiveMessage. Sobre el hecho de que la API nativa Win32 de MSMQ (MQCreateQueue, MQSendMessage, MQReceiveMessage, etc.) está documentada para aplicaciones C/C++, y de que permite crear, enviar y recibir en la cola sin pasar por la API administrada. 

  10. Microsoft Learn, Sugerencias de tabla (Transact-SQL). Sobre el hecho de que READPAST es una sugerencia que salta, sin leerlas, las filas bloqueadas por otras transacciones, de que solo puede saltar bloqueos a nivel de fila (no a nivel de página), y de que solo se puede especificar con los niveles de aislamiento READ COMMITTED o REPEATABLE READ. En particular, sobre la indicación de que «si la opción de base de datos READ_COMMITTED_SNAPSHOT está establecida en ON y, además, (a) el nivel de aislamiento de transacciones de la sesión es READ COMMITTED, o (b) la consulta también especifica la sugerencia de tabla READCOMMITTED, no se puede especificar la sugerencia de tabla READPAST. Para especificar la sugerencia READPAST en estos casos, elimine la sugerencia de tabla READCOMMITTED si está presente e incluya la sugerencia de tabla READCOMMITTEDLOCK en la consulta». Consulte también en la misma página que READCOMMITTEDLOCK es una sugerencia que fuerza un READ COMMITTED basado en bloqueos independientemente de la configuración de READ_COMMITTED_SNAPSHOT, y que no se pueden especificar dos o más sugerencias de granularidad (PAGLOCK / NOLOCK / READCOMMITTEDLOCK / ROWLOCK / TABLOCK / TABLOCKX) sobre una misma tabla. La configuración del lado de la base de datos se puede verificar con is_read_committed_snapshot_on en sys.databases 2

  11. Microsoft Learn, TOP (Transact-SQL). Sobre el hecho de que, al usar TOP con INSERT, UPDATE, MERGE o DELETE, las filas referenciadas no se ordenan de ninguna manera en particular, y de que, si se desea determinar el orden, hay que usar una subconsulta que combine TOP con ORDER BY

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿MSMQ ha sido discontinuado?
No. A fecha de julio de 2026, MSMQ no figura ni en la lista de funciones en desuso de los clientes Windows ni en la lista de «funciones eliminadas o cuyo desarrollo ha finalizado» de Windows Server. Se sigue incluyendo como función opcional en los sistemas operativos actuales. La idea de que «ha sido discontinuado» se ha extendido porque se confunde con la situación del lado de .NET. La biblioteca de clases estándar para manejar MSMQ, System.Messaging, solo existe en .NET Framework y nunca se portó a .NET (Core en adelante). En otras palabras, el estado exacto es: «sigue existiendo como función del sistema operativo, pero no hay una vía oficial de uso desde .NET moderno».
¿Hay alguna forma de usar MSMQ desde .NET 8 o .NET 10?
No existe una API administrada oficial. System.Messaging es una API que llega hasta .NET Framework 4.8.1 y no está incluida en el paquete de compatibilidad de Windows (Microsoft.Windows.Compatibility). Técnicamente es posible llamar a la API nativa Win32 de MSMQ (como MQSendMessage) mediante P/Invoke, pero eso implica crear y mantener usted mismo un contenedor (wrapper) que incluya los formateadores y la integración transaccional. Del lado de la comunidad, el proyecto CoreWCF publica un paquete para el transporte MSMQ (CoreWCF.MSMQ), pero está pensado para hospedar en .NET moderno los servicios WCF a los que se llama a través de una cola (es decir, portar el lado servidor de WCF); no es una API de cola genérica que sustituya a System.Messaging ni una alternativa para el cliente emisor. Además, su implementación depende de un port comunitario de System.Messaging para .NET Framework. Puede servir como opción de validación o para una prórroga provisional. CoreWCF en sí cuenta con una política de soporte oficial de Microsoft, pero eso no significa que el port comunitario de System.Messaging del que depende esta implementación de MSMQ tenga la misma garantía; si va a usarlo como base de un sistema de negocio, debe verificar si la versión que emplea está cubierta por la política de soporte y cómo se trata esa dependencia. En la práctica, lo más sensato es migrar también la cola en el momento en que se actualiza la aplicación a .NET.
¿Qué destino de migración es mejor, RabbitMQ o Azure Service Bus?
Antes de elegir entre esas dos opciones, considere usar una tabla de la base de datos como cola. En la mayoría de los sistemas de negocio de tamaño pequeño o mediano que usan MSMQ, el destino de la cola es un proceso que actualiza la propia base de datos de la empresa. En ese caso, con una cola de tabla se puede confirmar la «extracción del mensaje» y la «actualización de los datos de negocio» dentro de la misma transacción local que los datos de negocio, sustituyendo con un mecanismo más simple la consistencia que antes proporcionaba MSMQ combinado con transacciones distribuidas (DTC). Para los requisitos que una cola de tabla no cubre —por ejemplo, la distribución débilmente acoplada entre varios sistemas o la necesidad de un rendimiento (throughput) alto—, conviene evaluar RabbitMQ si el requisito de instalación local (on-premise) es fuerte, o Azure Service Bus si se puede alojar en la nube. Seguir este orden reduce el riesgo de errores.
¿Es válido decidir dejarlo congelado sobre .NET Framework por el momento?
Sí, de forma condicional. .NET Framework 4.8 recibe soporte como componente de Windows siguiendo el ciclo de vida del sistema operativo, y como MSMQ en sí no está en desuso, se puede prever que «seguirá funcionando». Sin embargo, si opta por dejarlo congelado, haga como mínimo estas cuatro cosas: indique explícitamente en el procedimiento de preparación de equipos (kitting) la activación de la función MSMQ, implemente un monitoreo de la longitud de la cola y del diario (journal), documente el formato de los mensajes y la configuración de conexión, y deje un procedimiento de recuperación previendo el cambio de personal a cargo. El verdadero riesgo de dejarlo congelado no es técnico, sino que «deje de haber alguien que pueda tocarlo».

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog