RabbitMQ.Services 2026.10.8.1

dotnet add package RabbitMQ.Services --version 2026.10.8.1
                    
NuGet\Install-Package RabbitMQ.Services -Version 2026.10.8.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RabbitMQ.Services" Version="2026.10.8.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RabbitMQ.Services" Version="2026.10.8.1" />
                    
Directory.Packages.props
<PackageReference Include="RabbitMQ.Services" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RabbitMQ.Services --version 2026.10.8.1
                    
#r "nuget: RabbitMQ.Services, 2026.10.8.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RabbitMQ.Services@2026.10.8.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RabbitMQ.Services&version=2026.10.8.1
                    
Install as a Cake Addin
#tool nuget:?package=RabbitMQ.Services&version=2026.10.8.1
                    
Install as a Cake Tool

RabbitMQ.Services

A .NET library that simplifies integrating RabbitMQ into ASP.NET Core applications. It provides dependency injection extensions, a consumer hosted service, an outbox pattern implementation, and a URI-based endpoint configuration model.

Features

  • URI-based RabbitMQ endpoint configuration
  • Consumer hosted service with automatic retry and delay support
  • Automatic reconnection of consumers after a broker restart
  • Outbox pattern for reliable message delivery via Entity Framework Core
  • DNS-based cluster resolution
  • OpenTelemetry activity propagation

Requirements

  • .NET 9 or .NET 10
  • RabbitMQ.Client 7.x
  • Microsoft.EntityFrameworkCore.Relational (for the outbox pattern)

Installation

dotnet add package RabbitMQ.Services

Getting Started

1. Register Core Services

Call AddRabbitMQ in your Program.cs or Startup.cs:

services.AddRabbitMQ();

This registers all internal infrastructure services (connection factory, endpoint parser, DNS resolver, etc.).


2. Consuming Messages

Define a Message
public class OrderCreatedMessage : BaseMessage
{
    public int OrderId { get; set; }
}

BaseMessage provides TraceId and SpanId properties used for distributed tracing.

Implement a Handler

Extend BaseMessageHandler<T> and override HandleAsync:

public class OrderCreatedHandler : BaseMessageHandler<OrderCreatedMessage>
{
    public override async Task HandleAsync(OrderCreatedMessage message, CancellationToken token)
    {
        // process the message
    }
}

Override HandleAsync(T message, int retryAttempt, CancellationToken token) or the full overload with delayAttempt if you need retry/delay context.

Tracing the Handler

BaseMessage carries the TraceId and SpanId of the publisher's Activity (they are stored by the outbox together with the message). To continue that trace in the handler, open the consumer span through IActivityBuilder:

public class OrderCreatedHandler(IActivityBuilder activityBuilder) : BaseMessageHandler<OrderCreatedMessage>
{
    public override async Task HandleAsync(OrderCreatedMessage message, CancellationToken token)
    {
        using var activity = activityBuilder.StartNewChildActivity<OrderCreatedHandler>(message);
        // process the message: spans opened here (HttpClient, database, ...) belong to the publisher's trace
    }
}

The span comes from the ActivitySource named ActivityBuilder.ActivitySourceName ("RabbitMQ.Services"), so subscribe your tracer to it, for example with OpenTelemetry:

services.AddOpenTelemetry().WithTracing(tracing => tracing.AddSource(ActivityBuilder.ActivitySourceName));

Without a listener the builder still starts a plain Activity (so Activity.Current is available for log correlation) and marks it recorded, so spans created under it by other instrumented libraries are sampled.

Register the Consumer Hosted Service
services.AddConsumerHostedService<OrderCreatedMessage, OrderCreatedHandler>(configuration);
Configuration (appsettings.json)
{
  "RabbitMQ": {
    "Consumers": {
      "Defaults": {
        "MaxRetryCount": 3
      },
      "OrderCreatedMessage": {
        "Url": "amqp://user:password@localhost/orders/order.created"
      }
    }
  }
}

The section name under Consumers must match the message type name (typeof(TMessage).Name).

You can also configure the consumer programmatically using the optional configureOptions action:

services.AddConsumerHostedService<OrderCreatedMessage, OrderCreatedHandler>(
    configuration,
    config =>
    {
        config.Url = "amqp://user:password@localhost/orders/order.created";
        config.MaxRetryCount = 5;
    });
Consumer Configuration Options
Property Default Description
Url (required) RabbitMQ endpoint URI
ConnectionName Handler full type name AMQP connection name
MaxRetryCount 3 Number of retry attempts before dead-lettering
MaxDelays null Maximum number of delay attempts
DelayInSeconds null Delay between retry attempts in seconds
BindQueue true Whether to declare and bind the queue on startup
Delaying Message Processing

Throw DelayMessageException from a handler to reschedule the message:

throw new DelayMessageException(TimeSpan.FromSeconds(30), "Not ready yet");
Connection Recovery

The client's built-in automatic recovery is switched off; ConsumerHostedService supervises the consumer instead. It connects with retries on startup, and when the broker connection drops it stops the consumer and connects again, retrying every second until the broker is back or the application shuts down. Nothing has to be configured, and a broker restart no longer requires restarting the application.

Every step of that path is bounded, so a broker that accepts TCP but never answers cannot hang a consumer silently:

  • A connect attempt is cancelled after 60 seconds. Consumers that share a ConnectionName share one attempt and wait for its result rather than for a lock, so one slow connect never queues the others.
  • A start attempt (connect plus channel setup) is abandoned after 90 seconds and retried.
  • While connected, the supervisor checks IsConnected every 30 seconds and reconnects if the connection or the channel is closed even though no event reported it.

IAsyncMessageConsumer<T> reports the drop through its ConnectionLost event (raised for both a connection and a channel shutdown) and never recovers on its own. Handlers of that event run on the client's event dispatcher and must return immediately. StartAsync and StopAsync take a CancellationToken; IsConnected is a snapshot of the connection and channel state.


3. Sending Messages (Outbox Pattern)

The outbox pattern stores messages in your database within the same transaction as your business data, guaranteeing at-least-once delivery.

Implement IOutboxDbContext

Your DbContext must implement IOutboxDbContext:

public class AppDbContext : DbContext, IOutboxDbContext
{
    // EF Core already provides Set<T>() and SaveChangesAsync
}
Add the Outbox Table

In OnModelCreating, call:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.AddOutboxEntities("outbox_messages");
    // optionally specify a schema: modelBuilder.AddOutboxEntities("outbox_messages", "myschema");
}
Register Outbox Services
services.AddOutboxServices<AppDbContext>(configuration);
Configuration (appsettings.json)
{
  "RabbitMQ": {
    "Outbox": {
      "ConnectionName": "my-service-producer",
      "Namespace": "my-service"
    }
  }
}
Send a Message

Inject IAsyncMessageSender and call SendMessageAsync:

public class OrderService(IAsyncMessageSender sender)
{
    public async Task CreateOrderAsync()
    {
        // ... business logic ...

        await sender.SendMessageAsync(
            "amqp://user:password@localhost/orders/order.created",
            new OrderCreatedMessage { OrderId = 42 });

        // Commit both business data and outbox message in one transaction
        await dbContext.SaveChangesAsync();
    }
}
Deliver Outbox Messages

Inject IMessageDeliveryService and call SendMessagesAsync periodically (e.g., from a background service or a scheduled job):

await deliveryService.SendMessagesAsync();

RabbitMQ Endpoint URI Format

Endpoints are specified as URIs with the amqp:// or rabbitmq:// scheme:

amqp://[user:password@]host[:port]/[vhost/]queue[?param=value&...]

Examples

amqp://localhost/myqueue
amqp://user:pass@localhost/myvhost/myqueue
amqp://localhost/myqueue?exchangetype=direct&route=my.routing.key
amqp://localhost/myqueue?consumers=4&prefetch=10
amqp://localhost/myqueue?temporary=true
amqp://localhost/myqueue?hosts=host1:5672,host2:5672

Credentials from the URI are masked when the endpoint is written to logs, e.g. amqp://***:***@localhost/myvhost/myqueue.

Query Parameters

Parameter Description
exchangetype Exchange type: fanout (default), direct, topic, headers
exchangename Override the exchange name (defaults to the queue name)
route Routing key used when binding or publishing
durable Queue durability (true/false/1/0; default: true)
exclusive Exclusive queue (true/false/1/0; default: false)
autodelete Auto-delete queue (true/false/1/0; default: false)
temporary Shorthand for durable=false&exclusive=true&autodelete=true
ha Make the queue a quorum queue (x-queue-type: quorum), replicated across the nodes of a cluster. The queue must be durable, not exclusive and not auto-delete; the error and delay queues of the advanced consumer follow it. Cannot be combined with another queue.x-queue-type
ttl Message TTL in milliseconds (x-message-ttl)
prefetch Consumer prefetch count (default: 1)
consumers Number of concurrent consumers (default: 1)
heartbeat Connection heartbeat interval: a number of seconds (60) or a .NET TimeSpan string (00:01:00); 0 turns the heartbeats off; default: the client's 60 s. A value that does not parse or is out of range (negative, over 65535 s) is ignored
connectiontimeout How long one connect to a node may take before the next node of the list is tried: a number of seconds (5) or a .NET TimeSpan string (00:00:05); default: the client's 30 s. A value that is not positive or does not parse is ignored
hosts Comma-separated host:port list for cluster connections
tx Enable transactional channel (true/false)
queue.* Pass arbitrary queue arguments (e.g. queue.x-dead-letter-exchange=dlx)
exchange.* Pass arbitrary exchange arguments

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.10.8.1 77 10/8/2026
2026.9.29.2 91 9/29/2026
2026.9.9.2 474 9/8/2026
2026.9.9.1 109 9/8/2026
2026.9.8.1 115 9/8/2026
2026.9.6.1 135 9/6/2026
2026.9.5.1 118 9/5/2026
2026.9.3.1 143 9/3/2026
2026.3.29.2 1,500 3/29/2026
2026.3.29.1 130 3/29/2026
2026.3.29 125 3/29/2026