O Wolverine é um framework .NET que funciona tanto como mediador em processo (o papel que o MediatR desempenha) quanto como um framework completo de mensageria assíncrona, com transportes para RabbitMQ, Azure Service Bus, Amazon SQS e Kafka (o papel que o MassTransit desempenha).
Os handlers são métodos simples, sem interfaces IRequest<T> e sem classes base, porque o Wolverine os conecta com código gerado em vez de reflexão em tempo de execução.
O MediatR passou a ter licença dupla na versão 13.0.0, em julho de 2025, oferecendo a Reciprocal Public License 1.5 ou uma licença comercial, enquanto o Wolverine continua sob MIT, sem nenhuma condição de elegibilidade (FAQ de licenciamento da Lucky Penny Software, consultado em 13 de setembro de 2026).
O que é o Wolverine no .NET?
O Wolverine é um framework de código aberto para tratamento de comandos e mensageria assíncrona no .NET, desenvolvido como parte da “Critter Stack”, ao lado do banco de dados de documentos Marten. Ele cobre duas tarefas que normalmente exigem bibliotecas separadas: a mediação de requisição/resposta em processo, em que substitui o MediatR, e a comunicação durável baseada em mensagens sobre RabbitMQ, Azure Service Bus, Amazon SQS ou Kafka, em que concorre com o MassTransit e o NServiceBus.
Em vez de resolver os handlers por reflexão e por um pipeline de middleware, o Wolverine usa geração de código com o Roslyn para compilar o caminho de despacho, então um handler é apenas um método Handle() público, dentro de uma classe *Handler, cujo primeiro parâmetro é do tipo da mensagem. É esse modelo de execução que diferencia o Wolverine. O próprio guia Message Handlers do Wolverine é enfático: “não há absolutamente nenhuma reflexão em tempo de execução dentro do pipeline de execução do Wolverine”.
Com isso, temos menos cerimônia e testes unitários mais fáceis (os handlers são métodos simples que podemos chamar diretamente). O Wolverine também traz recursos de produção que o MediatR nunca teve: inbox e outbox transacionais, sagas, mensagens agendadas e políticas de novas tentativas.
Primeiros passos com o Wolverine
Vamos começar a construir nossa primeira aplicação com a biblioteca Wolverine. Criamos um novo projeto de API com o comando:
dotnet new webapi -n IntroductionToWolverineLibrary
Isso cria um novo projeto de API mínima chamado IntroductionToWolverineLibrary, com suporte nativo a OpenAPI. Em seguida, instalamos a biblioteca Wolverine:
dotnet add package WolverineFx
Isso instala a versão mais recente de WolverineFx no nosso projeto.
A partir da linha 6.x, o Wolverine distribui seu compilador Roslyn de tempo de execução em um pacote separado, então também o instalamos. Sem ele, o Wolverine lança uma exceção na inicialização:
dotnet add package WolverineFx.RuntimeCompilation
Em seguida, no arquivo Program.cs, precisamos adicionar uma diretiva using Wolverine; e esta chamada:
builder.Host.UseWolverine();
Essa chamada disponibiliza o Wolverine em todo o nosso projeto. Agora estamos prontos para começar a construir nossa aplicação aproveitando a biblioteca Wolverine.
A biblioteca Wolverine como mediador
Para fins de demonstração, construímos o projeto como um sistema de gerenciamento de pedidos de livros. Primeiro, vamos criar um objeto simples para um novo pedido de livro. Mantemos os records no namespace IntroductionToWolverineLibrary.Models e adicionamos using IntroductionToWolverineLibrary.Models; a todos os arquivos que os usam:
public record Order(Guid OrderId, string CustomerName, int BookId);
Aqui, definimos um novo record Order, pensado para modelos de dados imutáveis. O objeto contém três propriedades. Primeiro, OrderId, um Guid (Globally Unique Identifier) que identifica o pedido. Depois, CustomerName, uma string que representa o nome do cliente. Por fim, BookId, um int que identifica o livro pedido.

E-book gratuito
Sua Web API está pronta para produção?
33 itens para verificar antes de implantá-la, com a correção de cada um. Um PDF gratuito de 76 páginas para .NET 10.
O e-book está em inglês.
Baixe o checklist gratuitoPDF gratuito. Um único e-mail para enviá-lo. Cancele a inscrição quando quiser.
InvokeAsync() para enviar uma mensagem
Agora, vamos configurar nosso primeiro endpoint no arquivo Program.cs. Vamos construir cada um dos nossos endpoints com a sintaxe das APIs mínimas:
app.MapPost("/order", async (Order newOrder, IMessageBus bus) => await bus.InvokeAsync(newOrder))
.WithName("NewBookOrder");
Aqui, definimos um endpoint HTTP POST na rota /order. Configuramos o endpoint para receber como parâmetros um objeto Order e uma instância de IMessageBus. Por fim, a expressão lambda fornecida executa de forma assíncrona o método InvokeAsync() no bus, passando newOrder como argumento.
A chamada a WithName("NewBookOrder") dá o nome NewBookOrder a esse endpoint, o que pode ser útil para roteamento ou documentação.
Agora, vamos construir o método que recebe a mensagem:
public class OrderHandler
{
public static void Handle(Order? order) => Console.WriteLine($"New order received: {order}");
}
Em uma nova classe, implementamos o método Handle, que recebe um objeto Order como parâmetro e imprime no console uma mensagem indicando que um novo pedido foi recebido. Como definimos um método chamado Handle que recebe um parâmetro Order em uma classe cujo nome termina em Handler, o Wolverine reconhece esse método como o handler das mensagens Order. Quando uma nova mensagem de pedido é recebida, o Wolverine usa o próprio barramento de mensagens local para roteá-la até esse método, que a processa.
Quando o Wolverine é integrado a uma aplicação .NET Core, ele registra o serviço IMessageBus no contêiner de IoC subjacente, o que permite injetá-lo em classes de controlador ou em endpoints de APIs mínimas, como vimos acima. Em seguida, o método IMessageBus.InvokeAsync(message) processa a mensagem fornecida, determinando o caminho de execução adequado para o tipo da mensagem e executando o(s) handler(s) correspondente(s) do Wolverine.
Não precisamos usar interfaces para declarar a intenção de certas classes, como IRequest ou IHandler. O Wolverine usa o Roslyn para gerar código em tempo de execução e, assim, reduzir ao mínimo o código normalmente necessário para ligar, por baixo dos panos, o handler correto ao comando adequado. Como consequência, podemos testar os métodos com mais facilidade. Em vez de criar um mock de uma abstração, podemos testar diretamente o método que contém a lógica de negócio. Como o método Handle é estático e recebe apenas a mensagem, podemos invocá-lo e testá-lo sem dependências.
Uso de InvokeAsync<T>() com objeto de retorno
Se quisermos que o handler retorne um objeto, precisamos usar o método IMessageBus.InvokeAsync<T>():
app.MapPost("/orderReply", async (Order newOrder, IMessageBus bus) =>
await bus.InvokeAsync<string>(newOrder))
.WithName("NewBookOrderReply");
Ao usar a sobrecarga IMessageBus.InvokeAsync<T>(message), esperamos que o handler retorne um objeto do tipo T. No nosso exemplo, esperamos uma resposta string simples.
Agora, vamos atualizar o método Handle para retornar uma resposta:
public static string Handle(Order? order) => $"New order received: {order}";
Esse método retorna uma string que confirma o recebimento de um novo pedido. Vale mencionar que podemos modificar o método Handle para retornar um objeto de uma classe ou de uma estrutura, mas não um tipo primitivo como int.
Uso de filas com a biblioteca Wolverine
A biblioteca Wolverine permite usar filas para enviar e receber nossas mensagens. Dessa forma, podemos nos comunicar, por meio de um canal, com diferentes entidades, como microsserviços ou APIs.
Vamos configurar, na chamada a UseWolverine() que já temos, o envio de mensagens para uma fila específica:
builder.Host.UseWolverine( x =>
{
x.PublishAllMessages().ToLocalQueue("local-queue");
});
No arquivo Program.cs, configuramos as mensagens para serem transmitidas por uma fila local chamada local-queue. Garantimos, assim, que qualquer mensagem que enviarmos ao IMessageBus do Wolverine seja processada de acordo com as regras configuradas no Wolverine.
Da mesma forma, vamos criar um novo objeto BookReview:
public record BookReview(int BookId, string ReviewerName, int Rating);

E-book gratuito
Sua Web API está pronta para produção?
33 itens para verificar antes de implantá-la, com a correção de cada um. Um PDF gratuito de 76 páginas para .NET 10.
O e-book está em inglês.
Baixe o checklist gratuitoPDF gratuito. Um único e-mail para enviá-lo. Cancele a inscrição quando quiser.
Esse record simples guarda as informações de uma nova resenha de livro. Agora, vamos configurar o novo endpoint:
app.MapPost("/bookReview", async (BookReview review, IMessageBus bus) =>
{
await bus.PublishAsync(review);
return Results.Ok("Book review submitted successfully.");
})
.WithName("BookReviewEndpoint");
Quando fazemos uma requisição POST a esse endpoint, a aplicação publica essa resenha de forma assíncrona usando o IMessageBus do Wolverine. Depois de publicar a mensagem, o endpoint retorna uma resposta HTTP indicando que a resenha foi enviada com sucesso. Essa configuração permite tratar as resenhas de livros de forma desacoplada, aproveitando os recursos do Wolverine para comunicação e processamento baseados em mensagens dentro da arquitetura da aplicação .NET.
Publicamos essa mensagem para todos os assinantes da fila. Essa é uma boa prática comum quando queremos emitir mensagens que funcionam como eventos. Isso é especialmente necessário em uma arquitetura em que queremos processar as mensagens de forma assíncrona e independente do remetente.
Agora, vamos implementar o handler:
public class BookReviewHandler
{
public static void Handle(BookReview? review) => Console.WriteLine($"New book review received: {review}");
}
Esse handler é invocado depois da transmissão da mensagem, já que o nome do método é Handle, o nome da classe termina em Handler e o argumento é do tipo BookReview. Nesse método, processamos BookReview da mesma forma, gerando uma string que confirma o recebimento da resenha.
O Wolverine registra as mensagens enfileiradas processadas com sucesso no nível Debug, então vamos definir esse nível para o namespace IntroductionToWolverineLibrary, com "IntroductionToWolverineLibrary": "Debug" dentro de Logging:LogLevel no appsettings.json, e verificar os logs no console:
Successfully processed message IntroductionToWolverineLibrary.Models.BookReview#01909954-3efa-401e-b0ac-f93465bbadc4 from local://local-queue/
O Wolverine gera um log quando processa uma mensagem enfileirada com sucesso. Como podemos ver aqui, o log indica que o Wolverine processou com sucesso uma mensagem do tipo BookReview do namespace IntroductionToWolverineLibrary.Models. A origem da mensagem é local://local-queue/, o que também indica que ela foi tratada a partir de uma fila local dentro da aplicação.
Filas externas para tratar mensagens
O Wolverine permite usar provedores de filas externos para tratar a mensageria. Por exemplo, podemos fazer a integração com sistemas de mensageria populares, como RabbitMQ, Apache Kafka, Azure Service Bus e Amazon SQS. O Wolverine então roteia as mensagens por esse broker, de modo que a comunicação assíncrona e o processamento distribuído rodam em uma infraestrutura feita para essa carga.
Ao usar o Wolverine para publicar e processar mensagens por meio de uma infraestrutura externa, podemos lidar com padrões de mensageria complexos, garantir a entrega confiável das mensagens e escalar nossa arquitetura de mensageria para atender às demandas de ambientes de alto tráfego.
Como o Wolverine se compara ao MediatR em C#?
As duas bibliotecas despacham um objeto de mensagem para um handler, mas diferem no mecanismo e no escopo. O MediatR exige que a mensagem implemente IRequest<TResponse> e que o handler implemente IRequestHandler<TRequest, TResponse>, resolve os handlers pelo contêiner de injeção de dependência em tempo de execução e fica estritamente dentro do processo.
O Wolverine elimina as interfaces por completo. Os métodos Handle() ou Consume() públicos de classes *Handler são descobertos por convenção e conectados com código gerado, e o mesmo handler pode, mais tarde, receber mensagens de um broker externo sem nenhuma alteração. O middleware também é diferente: os pipelines do MediatR são classes IPipelineBehavior, enquanto o Wolverine compõe o middleware dentro do código gerado, incluindo políticas convencionais de transação e de tratamento de erros.
O gatilho prático é o licenciamento. A partir da versão 13.0.0, de julho de 2025, o MediatR tem licença dupla: aceitar a Reciprocal Public License 1.5 e publicar nosso próprio código-fonte, cumprir as quatro condições do nível Community ou comprar uma licença comercial. O WolverineFx continua sob MIT, pura e simplesmente.
O MediatR ainda leva vantagem quando o objetivo é apenas o despacho em processo: é uma dependência menor, e suas interfaces tornam o contrato explícito no ponto de chamada. A migração, quando vale a pena, é quase toda mecânica: remover as interfaces marcadoras, renomear e refazer o registro.
| Critério | Wolverine | MediatR | MassTransit |
|---|---|---|---|
| Mediador em processo | Sim | Sim | Sim |
| Transportes para brokers de mensagens | RabbitMQ, Azure Service Bus, SQS, Kafka | Não | RabbitMQ, Azure Service Bus, SQS, Kafka |
| Estilo de handler | Método simples, geração de código | Interface IRequestHandler<T>, reflexão | Interface IConsumer<T> |
| Outbox/inbox durável | Sim, com um pacote de armazenamento (PostgreSQL, SQL Server) | Não | Sim, com um pacote de armazenamento |
| Sagas | Sim | Não | Sim |
| Licença | MIT, sem condições de elegibilidade (WolverineFx 6.36.0) | Licença dupla a partir da v13.0.0 (2025-07-02): RPL-1.5 ou comercial (MediatR 14.2.0); nível Community gratuito apenas se as quatro condições forem cumpridas; a v12.5.0 e as anteriores continuam sob Apache-2.0 | Comercial e com código-fonte disponível a partir da v9 (9.0.0, 2026-01-06), com chave de licença obrigatória em tempo de execução; a v8 e as anteriores continuam sob Apache-2.0 permanentemente e ainda recebem novas versões (8.5.10), mas o fornecedor as considera sem suporte e anunciou que a manutenção oficial da v8 não vai além de 2026; receita bruta anual inferior a US$ 1 milhão pode dar direito a um desconto de 100%, sem suporte comercial |
Para o padrão que o Wolverine substitui no lado do mediador, veja nosso guia sobre CQRS e MediatR no ASP.NET Core. No lado da mensageria, temos uma comparação entre Rebus, NServiceBus e MassTransit e um guia prático sobre como usar o MassTransit com RabbitMQ.
Conclusão
Neste artigo, apresentamos a biblioteca Wolverine para tratar a mensageria na nossa aplicação .NET. Com uma API, mostramos como configurar endpoints, configurar filas para a transmissão de mensagens e implementar handlers para o processamento assíncrono de mensagens.
Testado com .NET 10.0.10 e WolverineFx 6.36.0.