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
<PackageReference Include="RepletoryLib.Messaging.Outbox" Version="1.0.0" />
<PackageVersion Include="RepletoryLib.Messaging.Outbox" Version="1.0.0" />
<PackageReference Include="RepletoryLib.Messaging.Outbox" />
paket add RepletoryLib.Messaging.Outbox --version 1.0.0
#r "nuget: RepletoryLib.Messaging.Outbox, 1.0.0"
#:package RepletoryLib.Messaging.Outbox@1.0.0
#addin nuget:?package=RepletoryLib.Messaging.Outbox&version=1.0.0
#tool nuget:?package=RepletoryLib.Messaging.Outbox&version=1.0.0
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.
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 --
OutboxMessageentity 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:
- Polls the
OutboxMessagetable everyPollingIntervalSeconds - Fetches up to
BatchSizeunprocessed messages - Publishes each message via
IMessagePublisher - Marks successful messages as processed
- On failure, increments
RetryCountand schedulesNextRetryAtwith backoff - After
MaxRetryCountfailures, 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 | Versions 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. |
-
net10.0
- Microsoft.EntityFrameworkCore (>= 10.0.0)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.0)
- RepletoryLib.Common (>= 1.0.0)
- RepletoryLib.Messaging.Abstractions (>= 1.0.0)
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 |