*Finalizando a série sobre as bibliotecas .NET que deixaram — ou estão deixando — de ser open source e gratuitas, neste artigo apresento uma alternativa ao MassTransit e explico por que ela pode representar uma evolução em termos de arquitetura, simplicidade e performance.
O MassTransit sempre foi uma das opções mais populares no ecossistema .NET para implementar mensageria, comunicação assíncrona e padrões como Publish/Subscribe, Request/Response e Sagas. No entanto, com o anúncio do licenciamento pago nas versões mais recentes, muitos times começaram a buscar alternativas que mantenham boas práticas, mas sem o impacto de novos custos.
Além disso, o MassTransit, por ser uma solução robusta, pode adicionar uma camada extra de complexidade e overhead em cenários onde o foco é performance e simplicidade.
Foi nesse cenário que surgiu a necessidade de explorar o Wolverine — uma biblioteca moderna, open source e com um foco agressivo em alta performance, simplicidade e integração nativa com o .NET.
Por que considerar o Wolverine?
O Wolverine combina mensageria distribuída, transporte in-process e implementação do padrão Mediator, tudo em uma única solução. Ele se destaca por:
- Ser gratuito e open source.
- Eliminar dependências externas como MediatR.
- Oferecer suporte a mensageria in-process e distribuída (RabbitMQ, Azure Service Bus, Amazon SQS, Amazon SNS, Kafka, entre outros).
- Focar em alta performance, reduzindo alocações e overhead.
- Suportar Sagas e Process Managers com armazenamento de estado.
Comparativo Técnico — Wolverine vs MassTransit
Critério | MassTransit | Wolverine .NET |
---|---|---|
Licenciamento | Gratuito até a v8; novas versões exigem licença paga. | Gratuito e open source, sem custos para uso comercial. |
Complexidade da API | Robusta, rica em recursos, com curva de aprendizado maior. | Enxuta, declarativa e de fácil compreensão. |
Mensageria In-Process | Não possui nativamente. | Suporte completo a transporte in-process. |
Mensageria Distribuída | RabbitMQ, Azure Service Bus, Amazon SQS, Kafka, etc. | RabbitMQ, Azure Service Bus, Amazon SQS/SNS, Kafka, etc. |
Padrão Mediator | Depende de biblioteca externa como MediatR ou Mediator. | Implementa Mediator Pattern de forma nativa. |
Sagas e Process Managers | Suporte completo com persistência e timeouts. | Suporte a Sagas e stateful handlers com persistência. |
Integração com .NET Core | Alta integração, suporte a DI e middlewares. | Integração nativa com ASP.NET Core e minimal APIs. |
Performance e Overhead | Robusto, com overhead perceptível em cenários simples. | Foco agressivo em alta performance, baixo overhead. |
Extensibilidade | Suporte a middlewares, interceptadores e customizações. | API enxuta e extensível com simplicidade. |
Exemplo Prático: Configuração e Uso Básico do Wolverine
O Wolverine pode ser utilizado tanto para mensageria in-process quanto para comunicação assíncrona distribuída. A seguir, um exemplo simples com envio e consumo de mensagens.
Uso com Transporte In-Process
Ideal para iniciar projetos monolíticos ou aplicações que ainda não precisam de mensageria distribuída.
Instale o pacote:
dotnet add package WolverineFx
Defina a mensagem:
namespace Wolverine.Message;
public sealed record CreateMessage(Guid Id, string Content);
Defina o Handler:
using Wolverine.Message;
public sealed class CreateMessageHandler(ILogger<CreateMessageHandler> logger)
{
public void Handle(CreateMessage message) =>
logger.LogInformation("Message is: {message}", message);
}
Configure a Minimal API:
using Wolverine;
using Wolverine.Message;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseWolverine();
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
app.MapOpenApi();
app.UseHttpsRedirection();
app.MapPost("/message", async (CreateMessage request, IMessageBus messageBus) =>
{
await messageBus.SendAsync(request);
}).WithName("CreateMessage");
app.Run();
A cada POST
realizado no endpoint /message
, o método bus.SendAsync
publica a mensagem no barramento interno de mensagens do Wolverine (em memória). Essa mensagem é imediatamente roteada para o CreateMessageHandler
, que a processa de forma síncrona e eficiente, sem necessidade de um broker externo.
Uso com RabbitMQ
Crie dois projetos Console Application: um produtor e um consumidor.
Instale os pacotes em ambos:
dotnet add package WolverineFx
dotnet add package WolverineFx.RabbitMQ
Defina a mensagem:
namespace Wolverine.Message;
public sealed record MessageCreated(Guid Id, string Content, DateTime dateTime);
Produtor:
using Microsoft.Extensions.Hosting;
using Wolverine;
using Wolverine.RabbitMQ;
using Wolverine.RabbitMQ.Producer;
using Wolverine.Message;
using var host = Host.CreateDefaultBuilder()
.UseWolverine(options =>
{
const string exchangeName = "my-messages-exchange";
options.UseRabbitMq(c => c.HostName = "localhost")
.DeclareExchange(exchangeName, exchange =>
{
exchange.BindQueue("my-message-queue", "exchangeToMyMessages");
})
.AutoProvision();
options.PublishMessage<MessageCreated>().ToRabbitExchange(exchangeName);
options.Services.AddHostedService<ProducerBackgroundService>();
}).Build();
await host.RunAsync();
A fila my-message-queue
é configurada como o canal de envio no RabbitMQ.
public sealed class ProducerBackgroundService(IServiceProvider sp) : IHostedService
{
public async Task StartAsync(CancellationToken ct)
{
await using var scope = sp.CreateAsyncScope();
var bus = scope.ServiceProvider.GetRequiredService<IMessageBus>();
var logger = scope.ServiceProvider.GetRequiredService<ILogger<ProducerBackgroundService>>();
var count = 0;
while (!ct.IsCancellationRequested)
{
var message = new MessageCreated(Guid.NewGuid(), $"Content {count++}", DateTime.Now);
logger.LogInformation("Produced message is: {message}", message);
await bus.SendAsync(message);
await Task.Delay(TimeSpan.FromSeconds(30), ct);
}
}
public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
}
O método bus.SendAsync
publica uma mensagem na fila a cada 30 segundos.
Consumidor:
using Microsoft.Extensions.Hosting;
using Wolverine;
using Wolverine.RabbitMQ;
using var host = Host.CreateDefaultBuilder()
.UseWolverine(options =>
{
options.UseRabbitMq(c => c.HostName = "localhost").AutoProvision();
options.ListenToRabbitQueue("my-message-queue");
}).Build();
await host.RunAsync();
A fila my-message-queue
é configurada como o canal de recebimento do RabbitMQ.
public sealed class MessageCreatedHandler(ILogger<MessageCreatedHandler> logger)
{
public void Handle(MessageCreated message) =>
logger.LogInformation("Message created is: {message}", message);
}
O MessageCreatedHandler
consome as mensagens dessa fila, processando cada uma assim que chega.
Para ver o código completo, acesse o repositório no GitHub.
Conclusão
O Wolverine surge como uma alternativa moderna, leve e altamente performática para aplicações .NET orientadas a mensagens.
Além de eliminar a necessidade de licenciamento em cenários corporativos, o Wolverine se destaca por:
Oferecer mensageria in-process e distribuída em uma única solução.
Implementar o padrão Mediator de forma nativa, reduzindo dependências.
Priorizar alta performance, com foco em baixo overhead e simplicidade.
Ser gratuito e open source, sem custos adicionais ou restrições comerciais.
Para equipes que buscam reduzir a complexidade, evitar custos com licenciamento e manter uma arquitetura enxuta e escalável, o Wolverine se mostra uma opção altamente viável — especialmente em projetos que evoluem de monolitos para arquiteturas distribuídas.
🚀 E você, já conhecia o Wolverine?
💬 Está avaliando alternativas ao MassTransit?
Me conta nos comentários e vamos trocar experiências!
Precisa de apoio para decidir o futuro dos seus projetos — manter, evoluir ou começar do zero? Fale com a gente!
Nosso time de especialistas está pronto para ajudar você a enfrentar esses e outros desafios tecnológicos.
Referências
Top comments (0)