RepletoryLib.Messaging.Outbox 1.0.0

dotnet add package RepletoryLib.Messaging.Outbox --version 1.0.0
                    
NuGet\Install-Package RepletoryLib.Messaging.Outbox -Version 1.0.0
                    
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="RepletoryLib.Messaging.Outbox" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RepletoryLib.Messaging.Outbox" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="RepletoryLib.Messaging.Outbox" />
                    
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 RepletoryLib.Messaging.Outbox --version 1.0.0
                    
#r "nuget: RepletoryLib.Messaging.Outbox, 1.0.0"
                    
#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 RepletoryLib.Messaging.Outbox@1.0.0
                    
#: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=RepletoryLib.Messaging.Outbox&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=RepletoryLib.Messaging.Outbox&version=1.0.0
                    
Install as a Cake Tool

RepletoryLib.Messaging.Outbox

Transactional outbox pattern for reliable at-least-once message delivery with EF Core.

Part of the RepletoryLib ecosystem -- standalone, reusable .NET 10 libraries with zero business logic.

NuGet .NET 10 License: MIT


Overview

RepletoryLib.Messaging.Outbox implements the transactional outbox pattern to guarantee that messages are published reliably, even if the message broker is temporarily unavailable. Instead of publishing directly to RabbitMQ, messages are saved to an OutboxMessage table within the same database transaction as your business data. A background processor then publishes pending messages and handles retries.

Key Features

  • Transactional consistency -- Messages saved in the same DB transaction as business data
  • At-least-once delivery -- Background processor retries failed messages
  • Configurable retry -- Max retry count with exponential backoff
  • Batch processing -- Process multiple messages per polling cycle
  • EF Core integration -- OutboxMessage entity with fluent configuration

Installation

dotnet add package RepletoryLib.Messaging.Outbox

Dependencies

Package Type
RepletoryLib.Common RepletoryLib
RepletoryLib.Messaging.Abstractions RepletoryLib
Microsoft.EntityFrameworkCore NuGet (10.0.0)

Quick Start

using RepletoryLib.Messaging.Outbox;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRepletoryOutbox<AppDbContext>(builder.Configuration);

Add the outbox table to your DbContext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyOutboxConfiguration();
}
{
  "Messaging": {
    "Outbox": {
      "PollingIntervalSeconds": 10,
      "BatchSize": 50,
      "MaxRetryCount": 5,
      "RetryBackoffSeconds": 30
    }
  }
}

Configuration

OutboxOptions

Property Type Default Description
PollingIntervalSeconds int 10 How often the processor checks for pending messages
BatchSize int 50 Messages per processing cycle
MaxRetryCount int 5 Max retry attempts before giving up
RetryBackoffSeconds int 30 Base backoff between retries

Usage Examples

Writing to the Outbox in a Transaction

using RepletoryLib.Messaging.Outbox.Interfaces;
using RepletoryLib.Messaging.Outbox.Entities;

public class OrderService
{
    private readonly AppDbContext _context;
    private readonly IOutboxRepository _outbox;

    public OrderService(AppDbContext context, IOutboxRepository outbox)
    {
        _context = context;
        _outbox = outbox;
    }

    public async Task CreateOrderAsync(Order order)
    {
        // Both saved in the same transaction
        _context.Orders.Add(order);

        await _outbox.AddAsync(new OutboxMessage
        {
            Type = nameof(OrderCreatedEvent),
            Payload = JsonSerializer.Serialize(new OrderCreatedEvent
            {
                OrderId = order.Id,
                Total = order.Total
            })
        });

        await _context.SaveChangesAsync();
        // OutboxProcessor will pick up the message and publish it
    }
}

How the Processor Works

The OutboxProcessor is a BackgroundService that:

  1. Polls the OutboxMessage table every PollingIntervalSeconds
  2. Fetches up to BatchSize unprocessed messages
  3. Publishes each message via IMessagePublisher
  4. Marks successful messages as processed
  5. On failure, increments RetryCount and schedules NextRetryAt with backoff
  6. After MaxRetryCount failures, stops retrying and logs the error

Integration with Other RepletoryLib Packages

Package Relationship
RepletoryLib.Messaging.Abstractions IMessagePublisher used by the processor to publish messages
RepletoryLib.Messaging.RabbitMQ Actual transport for published messages
RepletoryLib.Data.EntityFramework Shares DbContext for transactional consistency

Troubleshooting

Issue Solution
Messages stuck in outbox Check that IMessagePublisher is registered (e.g., AddRepletoryRabbitMQ)
Messages not retrying Verify MaxRetryCount > 0 and RetryBackoffSeconds is reasonable
Duplicate processing At-least-once delivery means consumers must be idempotent
Outbox table not created Ensure modelBuilder.ApplyOutboxConfiguration() is called and migrations are applied

License

This project is licensed under the MIT License.

Copyright (c) 2024-2026 Repletory.


For complete documentation, infrastructure setup, and configuration reference, see the RepletoryLib main repository.

Product Compatible and additional computed target framework versions.
.NET 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
1.0.0 44 3/2/2026