MediatR em projetos .NET: ainda vale a pena usar?

MediatR em projetos .NET: ainda vale a pena usar?
Publicado em 12/10/2026 por Admin

O MediatR tornou-se uma biblioteca bastante conhecida no ecossistema .NET, especialmente em projetos que utilizam Clean Architecture, CQRS e aplicações construídas com ASP.NET Core.

Durante anos, a biblioteca foi adotada por equipes que procuravam desacoplar controllers, organizar regras de negócio e separar responsabilidades em aplicações de médio e grande porte. Em muitos projetos, tornou-se comum criar um handler para praticamente cada operação do sistema, desde consultas simples até operações complexas de negócio.

Mas será que essa abordagem continua fazendo sentido em 2026?

Com a evolução do .NET, a maturidade dos recursos de injeção de dependência e a crescente preocupação com a complexidade arquitetural, vale a pena reavaliar quando o MediatR realmente agrega valor e quando pode representar uma camada adicional de abstração sem benefícios proporcionais.

Neste artigo, vamos entender como a biblioteca funciona, quais são suas vantagens, quais cuidados devem ser considerados e como decidir se ela faz sentido para um projeto novo ou existente.

O que é o MediatR?

O MediatR é uma biblioteca para comunicação entre componentes dentro do mesmo processo. Seu objetivo é permitir que uma parte da aplicação envie uma solicitação sem precisar conhecer diretamente a implementação responsável por processá-la.

Em vez de um controller chamar diretamente um serviço específico, ele pode enviar uma requisição ao mediador. A biblioteca encaminha essa solicitação para o handler correspondente.

Essa abordagem ajuda a reduzir o acoplamento entre quem solicita uma operação e quem executa sua lógica.

O MediatR oferece suporte a diferentes tipos de mensagens, incluindo:

  • Requests: solicitações que podem produzir uma resposta.

  • Commands: operações que representam uma intenção de executar uma ação.

  • Queries: solicitações destinadas à obtenção de informações.

  • Notifications: mensagens que podem ser processadas por múltiplos handlers.

É importante esclarecer que commands e queries são convenções arquiteturais. O MediatR fornece os mecanismos de comunicação, mas não obriga a aplicação a implementar CQRS nem define sozinho as regras dessa arquitetura.

Como funciona na prática?

Imagine uma API responsável por cadastrar pedidos.

Sem o MediatR, um controller poderia depender diretamente de um serviço de aplicação:

[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
    private readonly OrderService _orderService;

    public OrdersController(OrderService orderService)
    {
        _orderService = orderService;
    }

    [HttpPost]
    public async Task<IActionResult> Create(
        CreateOrderRequest request)
    {
        var orderId = await _orderService.CreateAsync(request);

        return Created(
            $"/api/orders/{orderId}",
            new { id = orderId });
    }
}

Essa abordagem é perfeitamente válida. O controller delega a operação para um serviço, que pode conter ou coordenar as regras necessárias para cadastrar o pedido.

Com o MediatR, a mesma operação pode ser organizada usando uma requisição e um handler.

Primeiro, definimos o comando:

using MediatR;

public sealed record CreateOrderCommand(
    string CustomerName,
    decimal Total) : IRequest<Guid>;

Depois, criamos o handler responsável pelo processamento:

using MediatR;

public sealed class CreateOrderHandler
    : IRequestHandler<CreateOrderCommand, Guid>
{
    public async Task<Guid> Handle(
        CreateOrderCommand request,
        CancellationToken cancellationToken)
    {
        // Aqui entrariam as regras de negócio,
        // a criação da entidade e a persistência.

        await Task.CompletedTask;

        return Guid.NewGuid();
    }
}

Por fim, o controller envia a requisição ao mediador:

using MediatR;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
    private readonly ISender _sender;

    public OrdersController(ISender sender)
    {
        _sender = sender;
    }

    [HttpPost]
    public async Task<IActionResult> Create(
        CreateOrderCommand command,
        CancellationToken cancellationToken)
    {
        var orderId = await _sender.Send(
            command,
            cancellationToken);

        return Created(
            $"/api/orders/{orderId}",
            new { id = orderId });
    }
}

O exemplo é ilustrativo: a persistência, a validação dos dados e as regras de negócio ainda precisam ser implementadas. Além disso, em uma aplicação real, é recomendável separar o DTO recebido pela API do comando interno quando os contratos externos e internos tiverem responsabilidades diferentes.

Observe a principal diferença: o controller não depende diretamente do handler ou do serviço concreto responsável pela operação.

Essa separação pode ser útil quando a aplicação possui muitos casos de uso e precisa manter uma organização consistente.

Por outro lado, para uma operação simples, ela também acrescenta tipos e arquivos que talvez não fossem necessários.

Quais são as vantagens de utilizar MediatR?

A biblioteca não torna automaticamente uma aplicação mais bem arquitetada. Seus benefícios dependem da forma como ela é utilizada.

Ainda assim, existem situações nas quais o MediatR oferece vantagens concretas.

1. Menor acoplamento entre controllers e casos de uso

Em aplicações ASP.NET Core, controllers frequentemente acumulam dependências de diversos serviços.

Imagine um controller responsável por pedidos que depende de serviços de cadastro, cancelamento, consulta, faturamento e atualização de status.

Com o crescimento do sistema, essa classe pode acumular muitas dependências e responsabilidades.

O MediatR permite que cada operação seja representada por uma solicitação específica, enviada por meio de uma interface como ISender.

Isso facilita a organização dos casos de uso e reduz a necessidade de o controller conhecer todos os serviços envolvidos.

Entretanto, é importante não confundir redução de dependências com eliminação de complexidade. Os handlers continuam existindo e precisam ser organizados adequadamente.

2. Organização dos casos de uso

Uma das aplicações mais interessantes do MediatR é a organização da camada de aplicação.

Em vez de concentrar operações diferentes em um grande serviço, cada caso de uso pode ter sua própria implementação.

Por exemplo:

  • CreateOrderCommand: cadastrar um pedido.

  • CancelOrderCommand: cancelar um pedido.

  • UpdateOrderStatusCommand: atualizar o status.

  • GetOrderByIdQuery: consultar um pedido.

  • GetOrdersQuery: pesquisar pedidos.

Essa organização facilita a localização do código responsável por cada comportamento.

Em projetos com muitos desenvolvedores, ela também pode tornar mais previsível a estrutura da aplicação.

No entanto, não é obrigatório criar um handler para cada método de serviço. A decisão deve considerar a complexidade e a autonomia de cada operação.

3. Integração com pipelines de processamento

Outro recurso importante são os behaviors, que permitem adicionar comportamentos ao processamento das requisições.

Eles podem ser utilizados para implementar funcionalidades transversais, como:

  • Validação de comandos.

  • Logging.

  • Métricas e observabilidade.

  • Medição de tempo de execução.

  • Determinados mecanismos de autorização.

  • Integração com transações, quando corretamente projetada.

Considere um behavior responsável por medir a duração de cada requisição:

using System.Diagnostics;
using MediatR;
using Microsoft.Extensions.Logging;

public sealed class LoggingBehavior<TRequest, TResponse>
    : IPipelineBehavior<TRequest, TResponse>
    where TRequest : notnull
{
    private readonly ILogger<LoggingBehavior<TRequest, TResponse>>
        _logger;

    public LoggingBehavior(
        ILogger<LoggingBehavior<TRequest, TResponse>> logger)
    {
        _logger = logger;
    }

    public async Task<TResponse> Handle(
        TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        var stopwatch = Stopwatch.StartNew();

        try
        {
            return await next();
        }
        finally
        {
            stopwatch.Stop();

            _logger.LogInformation(
                "Request {RequestType} executada em {ElapsedMs} ms",
                typeof(TRequest).Name,
                stopwatch.ElapsedMilliseconds);
        }
    }
}

O behavior envolve a execução do próximo componente do pipeline e registra a duração, inclusive quando ocorre uma exceção.

Esse tipo de funcionalidade pode ser útil para padronizar comportamentos que seriam repetidos em diversos handlers.

É importante lembrar que o exemplo não registra automaticamente todos os detalhes da operação. Para uma solução de observabilidade completa, também podem ser necessários correlation IDs, tracing distribuído e integração com as ferramentas utilizadas pela aplicação.

4. Facilita a separação entre comandos e consultas

Em projetos que adotam CQRS, o MediatR oferece uma forma prática de representar comandos e consultas como solicitações independentes.

Uma query pode retornar dados sem alterar o estado do sistema, enquanto um command representa uma operação que pode modificar esse estado.

Essa separação ajuda a organizar o código e permite que cada caso de uso evolua de maneira independente.

Entretanto, utilizar MediatR não significa que você implementou CQRS completo.

Uma aplicação pode utilizar commands e queries no mesmo projeto, compartilhando o mesmo banco de dados e o mesmo modelo de persistência.

CQRS também pode ser implementado sem MediatR, utilizando classes e interfaces próprias.

Quais são as desvantagens do MediatR?

Apesar dos benefícios, a biblioteca também apresenta custos que precisam ser considerados.

1. Mais abstrações e arquivos

Uma operação simples pode exigir a criação de diversos elementos:

  • Um DTO para a API.

  • Um command.

  • Um handler.

  • Um validator.

  • Uma interface ou abstração de persistência.

  • Uma entidade.

  • Um repositório.

Nem todos esses componentes são obrigatórios, mas projetos que adotam uma estrutura excessivamente formal podem acabar multiplicando arquivos sem necessidade.

Em aplicações pequenas, isso pode tornar a leitura e a manutenção mais trabalhosas.

Um desenvolvedor que deseja entender uma operação aparentemente simples pode precisar navegar por diversas classes até encontrar a lógica efetiva.

A arquitetura deve facilitar a compreensão do sistema, não transformar cada alteração em uma investigação.

2. Custos de manutenção

Cada abstração introduz um elemento adicional que precisa ser compreendido, testado e mantido.

Quando o MediatR é utilizado sem critérios, a equipe pode criar handlers para operações triviais, dividir excessivamente o código e dificultar a compreensão do fluxo de execução.

O problema não está na biblioteca em si, mas na utilização indiscriminada do padrão.

Uma boa regra é avaliar se a separação representa um caso de uso relevante ou apenas desloca algumas linhas de código de uma classe para outra.

3. Dependência de uma biblioteca externa

O MediatR é um projeto mantido fora do runtime do .NET. Portanto, sua adoção envolve acompanhar a evolução da biblioteca, suas condições de licenciamento, as versões disponíveis e a compatibilidade com a aplicação.

Também é importante verificar as condições comerciais e de licenciamento vigentes antes de utilizá-lo em novos projetos ou ampliar sua utilização em ambientes empresariais.

Essa análise deve ser feita com base nas informações oficiais do projeto, sem presumir que as condições atuais serão iguais às de versões anteriores.

O mesmo princípio vale para qualquer dependência externa importante.

4. Desempenho e indireção

O MediatR introduz uma camada de despacho entre quem envia a solicitação e quem a processa.

Essa indireção possui um custo de execução, mas isso não significa que ela será relevante em todas as aplicações.

Em operações que acessam bancos de dados, serviços externos ou sistemas de mensageria, o tempo de processamento dessas dependências frequentemente merece mais atenção do que o despacho interno.

Em cenários de altíssimo volume ou com operações extremamente pequenas, vale medir o custo adicional e comparar com uma chamada direta.

Não é adequado afirmar que o MediatR sempre melhora ou prejudica o desempenho. O resultado depende do cenário, da implementação e do perfil de carga.

MediatR ainda faz sentido com o .NET moderno?

Sim, mas não como uma regra obrigatória para qualquer aplicação.

O .NET oferece mecanismos de injeção de dependência, Minimal APIs, recursos de linguagem e ferramentas de observabilidade que permitem construir aplicações organizadas sem a necessidade de uma biblioteca mediadora.

Isso não elimina a utilidade do MediatR.

A decisão deve partir das necessidades arquiteturais do sistema.

Em uma aplicação com dezenas ou centenas de casos de uso, diferentes tipos de operações e necessidade de comportamentos transversais padronizados, a biblioteca pode oferecer uma estrutura consistente.

Em uma API pequena, com poucos endpoints e regras simples, a chamada direta a serviços de aplicação pode ser mais clara.

O tamanho do projeto também não deve ser o único critério. Uma aplicação pequena, mas com regras de negócio complexas, pode se beneficiar de uma separação explícita de casos de uso.

Da mesma forma, uma aplicação grande pode funcionar bem sem MediatR, desde que tenha uma organização adequada.

MediatR e Clean Architecture: qual é a relação?

Clean Architecture procura organizar o sistema de modo que as regras de negócio não dependam diretamente de detalhes externos, como frameworks, interfaces de usuário ou mecanismos de persistência.

Nesse contexto, o MediatR pode ser utilizado como mecanismo de comunicação entre a camada de entrada e os casos de uso.

Uma estrutura possível seria:

src/
├── MyApp.Api/
│   ├── Controllers/
│   └── Program.cs
│
├── MyApp.Application/
│   ├── Orders/
│   │   ├── Commands/
│   │   ├── Queries/
│   │   └── Handlers/
│   ├── Behaviors/
│   └── DependencyInjection.cs
│
├── MyApp.Domain/
│   ├── Entities/
│   └── ValueObjects/
│
└── MyApp.Infrastructure/
    ├── Persistence/
    └── Repositories/

Essa é apenas uma possibilidade de organização. A estrutura ideal depende do tamanho da aplicação, da divisão dos módulos e das convenções da equipe.

Também é importante compreender que o MediatR não implementa Clean Architecture por conta própria.

Uma aplicação pode utilizar a biblioteca e ainda apresentar dependências inadequadas, regras de negócio concentradas nos controllers ou domínio excessivamente acoplado à infraestrutura.

A qualidade arquitetural depende das decisões tomadas ao redor da biblioteca.

Uma observação sobre dependências

Se a camada de aplicação utiliza interfaces do MediatR, ela possui uma dependência dessa biblioteca.

Isso não significa necessariamente que a arquitetura esteja errada. O importante é avaliar se essa dependência é aceitável e se as regras de negócio permanecem protegidas de detalhes que não deveriam conhecer.

Se a equipe deseja eliminar a dependência de uma biblioteca mediadora, pode implementar uma abstração própria de despacho ou utilizar serviços de aplicação diretamente.

Essa decisão tem um custo de manutenção e deve ser justificada por uma necessidade concreta.

Quando vale a pena utilizar MediatR?

O MediatR tende a ser uma boa escolha quando:

  • A aplicação possui muitos casos de uso independentes.

  • A equipe precisa de uma convenção clara para commands e queries.

  • Existem behaviors úteis para vários tipos de requisição.

  • Os controllers estão acumulando muitas dependências.

  • O sistema utiliza uma organização baseada em casos de uso.

  • A equipe conhece a biblioteca e consegue manter sua estrutura com consistência.

Nesses cenários, a biblioteca pode ajudar a padronizar o fluxo de execução e facilitar a evolução do sistema.

Por outro lado, considere não utilizar MediatR quando:

  • A aplicação é pequena e possui regras de negócio simples.

  • Os serviços de aplicação já oferecem uma organização suficiente.

  • A equipe não precisa de despacho indireto ou de behaviors.

  • A quantidade de handlers dificulta a navegação pelo código.

  • A biblioteca foi adicionada apenas porque um template ou tutorial a utilizava.

A decisão deve ser baseada no benefício concreto para o projeto, e não na popularidade da ferramenta.

É possível remover o MediatR de um projeto existente?

Sim. Entretanto, remover uma dependência de uma aplicação em produção exige planejamento.

Antes de iniciar a mudança, identifique todos os pontos em que a biblioteca é utilizada:

  • Chamadas a ISender, IMediator ou interfaces relacionadas.

  • Handlers registrados no container de injeção de dependência.

  • Behaviors e demais componentes de pipeline.

  • Notifications e respectivos handlers.

  • Integrações com validação, logging e transações.

Em seguida, avalie como cada funcionalidade será substituída.

Para operações simples, uma chamada direta a um serviço de aplicação pode ser suficiente.

Para comportamentos transversais, pode ser necessário utilizar filtros, decorators, middleware ou outras soluções compatíveis com a arquitetura.

Não remova a biblioteca antes de compreender quais responsabilidades dependem dela. Caso contrário, o resultado pode ser a perda de funcionalidades importantes ou a criação de uma arquitetura ainda mais complexa.

Também não existe uma obrigação de remover MediatR de aplicações existentes apenas porque outras abordagens são possíveis. Se a biblioteca está funcionando bem e oferece benefícios reais, manter a solução pode ser a decisão mais econômica.

MediatR ou serviços de aplicação tradicionais?

A comparação pode ser resumida da seguinte maneira:

Critério MediatR Serviços de aplicação
Comunicação Despacho por requisições Chamadas diretas a métodos
Organização dos casos de uso Pode oferecer uma estrutura explícita por handler Depende da organização adotada
Complexidade inicial Maior Geralmente menor
Behaviors transversais Suporte por pipeline Exigem outras estratégias
Navegação pelo código Pode envolver várias classes Pode ser mais direta em projetos simples
Dependências externas Depende da biblioteca Pode funcionar sem biblioteca mediadora
Adequação a operações simples Depende do contexto Frequentemente suficiente
Adequação a muitos casos de uso Pode padronizar a organização Também é possível com boa estrutura

Nenhuma das alternativas é universalmente superior.

A melhor escolha é aquela que mantém o código compreensível, testável e fácil de evoluir sem introduzir complexidade desnecessária.

Conclusão: vale a pena usar MediatR em 2026?

O MediatR continua sendo uma opção válida para aplicações .NET que se beneficiam de uma comunicação desacoplada entre componentes, organização explícita dos casos de uso e comportamentos transversais padronizados.

No entanto, ele não deve ser tratado como requisito para Clean Architecture, CQRS ou qualquer aplicação ASP.NET Core.

Em projetos complexos, a biblioteca pode ajudar a manter uma estrutura consistente e facilitar a evolução do sistema.

Em aplicações simples, serviços de aplicação tradicionais podem entregar o mesmo resultado com menos abstrações.

Minha recomendação é começar pelas necessidades reais do projeto. Se o MediatR resolver um problema arquitetural concreto, sua utilização pode ser justificada. Se ele apenas multiplicar handlers e arquivos sem melhorar a organização, provavelmente não é necessário.

O objetivo não é utilizar o maior número possível de padrões e bibliotecas, mas construir uma aplicação que seja fácil de compreender, testar e manter.

E você, ainda utiliza MediatR nos seus projetos .NET?

Prefere organizar os casos de uso com commands e handlers ou trabalhar com serviços de aplicação tradicionais?

Compartilhe sua experiência nos comentários. A discussão é especialmente interessante para quem mantém aplicações empresariais que cresceram ao longo dos anos e precisa equilibrar arquitetura, produtividade e manutenção.