Alternativa a MediatR en .NET: 3 razones para migrar
En un proyecto que hice hace poco tuve que decidir cómo resolver el envío de comandos y consultas en .NET, y por primera vez la respuesta automática de «usa MediatR» ya no era tan automática. Buscando una alternativa a MediatR en .NET encontré varias opciones, pero solo una resolvía el problema de licencia sin sacrificar rendimiento. Esto es lo que decidí, por qué, y las dudas que me planteé antes de decidirme — porque un post honesto sobre esto tiene que incluir las objeciones, no solo la conclusión.
Qué cambió en MediatR y por qué importa
MediatR lleva años siendo la librería estándar del ecosistema .NET para implementar el patrón mediador. La versión 12.0, en febrero de 2023, fue un release normal — sin ningún cambio de licencia, y muchos artículos que circulan por ahí mezclan esa fecha con el cambio real, que ocurrió más de dos años después.
El cambio real llegó el 2 de julio de 2025: MediatR y AutoMapper pasaron a Lucky Penny Software, la empresa de Jimmy Bogard, bajo un modelo de licencia dual — Reciprocal Public License 1.5 más una licencia comercial de pago. La versión 12.5.0 fue la última publicada bajo Apache 2.0; el cambio de licencia entra en vigor a partir de la 13.0. Existe una licencia gratuita para equipos con ingresos anuales por debajo de un umbral determinado, uso educativo y entornos no productivos — pero depender de una librería cuyo uso gratuito está condicionado a cifras de negocio que pueden cambiar es un riesgo que, para un proyecto nuevo, prefiero no asumir desde el primer día. Por eso empecé a mirar una alternativa a MediatR en .NET en cuanto confirmé la fecha exacta del cambio.
La alternativa a MediatR en .NET que elegí
Cuando tuve que decidir, descarté seguir dependiendo de una librería con licencia comercial condicionada y elegí Mediator, de martinothamar: licencia MIT, sin restricciones de uso comercial, y con una diferencia técnica de fondo que no es solo una cuestión de licencia — resuelve el envío de comandos con generadores de código en tiempo de compilación, no por reflexión en tiempo de ejecución.
La API que expone es muy parecida a la de MediatR, así que migrar el código que ya conoces del patrón mediador no exige reaprender nada:
// El contrato es casi idéntico al de MediatR
public record CrearPedidoCommand(string ClienteId, List<LineaPedido> Lineas)
: IRequest<Guid>;
public class CrearPedidoCommandHandler : IRequestHandler<CrearPedidoCommand, Guid>
{
private readonly IPedidoRepository _repositorio;
public CrearPedidoCommandHandler(IPedidoRepository repositorio)
{
_repositorio = repositorio;
}
public async ValueTask<Guid> Handle(CrearPedidoCommand comando, CancellationToken cancellationToken)
{
var pedido = Pedido.Crear(comando.ClienteId, comando.Lineas);
await _repositorio.GuardarAsync(pedido, cancellationToken);
return pedido.Id;
}
}
La diferencia real está por debajo de esta clase, no en ella.
Cómo funciona por dentro: generadores de código, no reflexión
MediatR resuelve, en tiempo de ejecución, qué handler corresponde a cada comando o consulta, usando reflexión para inspeccionar tipos y construir el grafo de dependencias. Funciona bien, pero tiene un coste: cada resolución consume tiempo de CPU y, en aplicaciones con mucho tráfico, ese coste se nota.
Mediator resuelve lo mismo en tiempo de compilación: un generador de código analiza tus comandos, tus consultas y tus handlers, y genera el código de conexión entre ellos como parte de la compilación. Cuando la aplicación arranca, no hay ninguna búsqueda que hacer — ya está todo conectado, como si lo hubieras escrito tú mismo a mano. Esto trae dos beneficios prácticos: es más rápido en el envío de cada comando (según los propios benchmarks publicados por la librería, varias veces más rápido que la resolución por reflexión), y es compatible con Native AOT — la compilación ahead-of-time que necesita saber en tiempo de compilación qué código se va a ejecutar, algo que la reflexión dinámica de MediatR dificulta.
Hay un beneficio adicional menos conocido: los errores de conexión —un comando sin handler, por ejemplo— se detectan al compilar, no al ejecutar en producción y descubrir en el peor momento que falta una pieza.
ValueTask en vez de Task: un detalle que sí importa
Mediator usa ValueTask<T> como tipo de retorno en vez de Task<T>. La diferencia parece cosmética pero no lo es: Task<T> siempre reserva memoria en el heap para representar la operación asíncrona, incluso cuando el resultado ya está disponible de forma síncrona. ValueTask<T> evita esa reserva cuando no hace falta, y solo se comporta como una tarea real cuando la operación es verdaderamente asíncrona. En handlers que se ejecutan muchas veces por segundo, ese ahorro de asignaciones reduce el trabajo del recolector de basura de forma medible.
Las objeciones que me hice antes de decidirme
Ningún cambio de librería está libre de riesgo, y estas son las preguntas que me hice antes de decidirme, no después:
¿Es Mediator suficientemente maduro para producción? Tiene miles de descargas, mantenimiento activo, y varios miles de estrellas en su repositorio público. No es Microsoft, es un desarrollador independiente — eso es un riesgo real de continuidad a largo plazo, el mismo riesgo que existe con cualquier librería de código abierto mantenida por una sola persona. Lo sopesé frente al riesgo ya materializado de depender de una librería que cambió sus condiciones de un día para otro, y para un proyecto nuevo me pareció el riesgo menor de los dos.
¿Y si Mediator también cambia de licencia en el futuro? No hay garantía de que no ocurra — ninguna licencia de código abierto la da. Lo que sí cambia es la situación de partida: MIT es una licencia permisiva desde el origen, sin cláusula de «gratis hasta cierto tamaño de empresa» que pueda activarse más adelante.
¿Compensa migrar código ya escrito con MediatR? Depende del tamaño del proyecto y de cuánto código depende directamente de la API de MediatR más allá de los IRequestHandler. Para un proyecto nuevo, la decisión es sencilla. Para uno existente, evaluaría primero cuánto cuesta quedarse en la última versión con licencia abierta (12.5.0) mientras se decide con calma, frente a migrar ya.
¿Y si el equipo no conoce generadores de código y le cuesta depurar lo que generan? Es una objeción real y la tuve en cuenta. Los generadores de código añaden una capa de «magia» que, cuando algo falla, puede ser más difícil de depurar que un error de reflexión en tiempo de ejecución, porque el código generado no siempre es evidente a primera vista. En la práctica, el código generado se puede inspeccionar como cualquier otro archivo del proyecto, y una vez que el equipo entiende que ahí es donde mirar, la curva de aprendizaje es corta — pero es honesto reconocer que existe.
Cómo es migrar código existente
Si ya tienes un proyecto con MediatR y decides evaluar esta alternativa a MediatR en .NET, la buena noticia es que la API de comandos y handlers es casi idéntica: cambiar el espacio de nombres y el paquete NuGet cubre la mayor parte del trabajo en proyectos donde el uso de la librería se limita a IRequest, IRequestHandler y el propio mediador para enviarlos. Donde sí hay que revisar con calma es en los pipeline behaviors — el mecanismo de comportamientos transversales existe en las dos librerías, pero la forma de registrarlos y su interfaz exacta no son intercambiables sin tocar código. Para un proyecto pequeño, esa revisión se hace en un rato; para uno grande, con decenas de behaviors ya escritos, es el coste real que hay que sopesar antes de decidir migrar.
Cuándo NO cambiarías de MediatR
Si tu proyecto ya está en producción con MediatR y tu empresa cumple los requisitos de la licencia gratuita que ofrece Lucky Penny Software, migrar por principio, sin una necesidad técnica real, es cambiar una dependencia estable por otra sin ganar nada a cambio salvo el propio cambio. Reservaría la migración a una alternativa a MediatR en .NET para proyectos nuevos, o para proyectos donde el rendimiento del envío de comandos —alto volumen, baja latencia— ya es una preocupación real, no hipotética.
No cambiaría tampoco solo por moda o porque «todo el mundo está migrando». La decisión que cuento en este post respondía a un riesgo concreto de licencia y a un beneficio técnico real de rendimiento — no a seguir una tendencia. Si tu proyecto no tiene ninguno de los dos problemas, quedarte donde estás sigue siendo una decisión razonable, y cambiar de librería sin una razón concreta detrás es exactamente el tipo de reescritura que no aporta nada al negocio, solo trabajo nuevo.
Si quieres ver primero cómo organizaba CQRS con MediatR antes de este cambio, lo cuento en CQRS con MediatR en .NET.
¿Estás empezando un proyecto .NET nuevo y decidiendo qué piezas de infraestructura usar desde el principio, incluida si necesitas evaluar una alternativa a MediatR en .NET? En Desarrollo .NET a medida tomo este tipo de decisiones con este mismo criterio: no por costumbre, sino evaluando el riesgo real de cada dependencia antes de que forme parte del proyecto.
Fuentes externas citadas: AutoMapper and MediatR Commercial Editions Launch Today, Jimmy Bogard — el anuncio oficial del cambio de licencia, del propio autor de MediatR; repositorio oficial de Mediator, martinothamar — la alternativa MIT descrita en este post.
