VOOZH about

URL: https://www.nuget.org/packages/ZeroAlloc.Outbox/

โ‡ฑ NuGet Gallery | ZeroAlloc.Outbox 2.5.0


๏ปฟ

๐Ÿ‘ Image
ZeroAlloc.Outbox 2.5.0

dotnet add package ZeroAlloc.Outbox --version 2.5.0
 
 
NuGet\Install-Package ZeroAlloc.Outbox -Version 2.5.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="ZeroAlloc.Outbox" Version="2.5.0" />
 
 
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ZeroAlloc.Outbox" Version="2.5.0" />
 
Directory.Packages.props
<PackageReference Include="ZeroAlloc.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 ZeroAlloc.Outbox --version 2.5.0
 
 
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: ZeroAlloc.Outbox, 2.5.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 ZeroAlloc.Outbox@2.5.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=ZeroAlloc.Outbox&version=2.5.0
 
Install as a Cake Addin
#tool nuget:?package=ZeroAlloc.Outbox&version=2.5.0
 
Install as a Cake Tool
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

ZeroAlloc.Outbox

๐Ÿ‘ NuGet
๐Ÿ‘ Build
๐Ÿ‘ AOT
๐Ÿ‘ GitHub Sponsors

Source-generated transactional outbox for .NET. Annotate a message type with [OutboxMessage] and a Roslyn source generator emits a typed writer and dispatcher bridge โ€” no reflection, no boxing, AOT-safe. Backed by EF Core (production) or in-memory (tests), with a built-in polling worker, exponential-backoff retry, and dead-letter support.

Multiple packages in this family โ€” see Documentation or NuGet for the full list.


Install

The source generator is bundled into the main package โ€” a single PackageReference is all you need:

# Core abstractions + source generator (always required)
dotnet add package ZeroAlloc.Outbox

# Pick a store:
dotnet add package ZeroAlloc.Outbox.EfCore # production โ€” Entity Framework Core
dotnet add package ZeroAlloc.Outbox.InMemory # testing โ€” in-process, no database

The standalone ZeroAlloc.Outbox.Generator package is still published for backwards compatibility with existing direct PackageReferences, but new consumers should reference only ZeroAlloc.Outbox.


Quick start

1. Annotate your message:

using ZeroAlloc.Outbox;

[OutboxMessage]
public sealed record OrderPlaced(int OrderId, decimal Amount);

The generator emits IOutboxWriter<OrderPlaced> and its DI registration extension.

2. Register with DI:

builder.Services.AddOutbox(options =>
 {
 options.PollingInterval = TimeSpan.FromSeconds(5);
 options.BatchSize = 50;
 options.MaxAttempts = 3;
 })
 .WithEfCore<AppDbContext>() // or .WithInMemoryStore()
 .AddOrderPlacedOutbox(); // generated extension

3. Write in a transaction:

public class OrderService(IOutboxWriter<OrderPlaced> writer, AppDbContext db)
{
 public async Task PlaceOrderAsync(Order order, CancellationToken ct)
 {
 db.Orders.Add(order);
 await db.SaveChangesAsync(ct);
 await writer.WriteAsync(new OrderPlaced(order.Id, order.Total), ct: ct);
 }
}

For atomic writes (both or neither commit), pass the DbTransaction explicitly. See EF Core Transaction.

4. Implement a dispatcher:

public class OrderPlacedDispatcher(IMessageBus bus) : IOutboxDispatcher<OrderPlaced>
{
 public async Task DispatchAsync(OrderPlaced message, CancellationToken ct)
 => await bus.PublishAsync(message, ct);
}

// Register the dispatcher
builder.Services.AddTransient<IOutboxDispatcher<OrderPlaced>, OrderPlacedDispatcher>();

Dashboard

Operate the outbox at runtime: inspect pending / retry / dead-lettered / dispatched messages, watch a live throughput chart, and requeue or cancel individual messages.

Add the package, then register the event publisher and map the endpoints:

dotnet add package ZeroAlloc.Outbox.Dashboard
// Register the publisher (required for SSE live updates)
builder.Services.AddOutbox().WithDashboardEvents();

// Map the dashboard endpoints
app.MapOutboxDashboard("/outbox");

// Optional: protect with auth
app.MapOutboxDashboard("/outbox").RequireAuthorization("AdminPolicy");

The mapped root (/outbox) serves the HTML dashboard; REST endpoints (snapshot, throughput, requeue, cancel, force-dispatch) and the SSE stream (events) live under the same prefix.

Security

The dashboard exposes write actions (requeue, cancel, force-dispatch) as POST endpoints:

  • POST /outbox/api/messages/{id}/requeue
  • POST /outbox/api/messages/{id}/cancel
  • POST /outbox/api/messages/{id}/force-dispatch

Never mount the dashboard unauthenticated in a production environment. Always apply authentication/authorization:

app.MapOutboxDashboard("/outbox").RequireAuthorization("AdminPolicy");

The IEndpointConventionBuilder returned by MapOutboxDashboard supports all standard ASP.NET Core auth middleware (RequireAuthorization, AllowAnonymous, route filters, etc.).

CSRF protection is the host application's responsibility โ€” the dashboard does not emit or validate anti-forgery tokens. If your authentication scheme is cookie-based, apply the standard ASP.NET Core [ValidateAntiForgeryToken] or enable the antiforgery middleware as appropriate.

What the dashboard shows

  • Pending โ€” messages awaiting their first dispatch attempt
  • Retry queue โ€” messages that have failed at least once and are scheduled for retry
  • Dead-lettered โ€” messages that exceeded MaxAttempts, with the last failure reason
  • Dispatched โ€” most-recently succeeded messages
  • Throughput โ€” SVG chart of dispatched + failed counts per minute
  • Actions โ€” Requeue a dead-lettered message ยท Cancel a pending one ยท Force dispatch to run it now
Tab Screenshot
Pending โ€” queue of messages awaiting first dispatch ๐Ÿ‘ Pending tab
Retry โ€” failed messages with back-off schedule ๐Ÿ‘ Retry tab
Dead-lettered โ€” exhausted retries with last error ๐Ÿ‘ Dead-lettered tab
Dispatched โ€” recently-succeeded history feeding the throughput chart ๐Ÿ‘ Dispatched tab

The dashboard is fully responsive โ€” tablet (768 ร— 1024) and mobile (375 ร— 812) captures live in docs/screenshots/.

Blazor component

For apps already using Blazor, ZeroAlloc.Outbox.Dashboard.Blazor ships an <OutboxDashboard /> component that embeds the dashboard via iframe:

dotnet add package ZeroAlloc.Outbox.Dashboard.Blazor
@* In any Razor page / component *@
<OutboxDashboard BaseUrl="/outbox" />

You still need MapOutboxDashboard("/outbox") โ€” the Blazor component is a thin wrapper around the mapped endpoints.


Performance

Correctness-matched overhead vs a hand-rolled SQLite outbox (same connection, both transactional). .NET 10.0.7, i9-12900HK, BenchmarkDotNet v0.15.4.

Operation Hand-rolled ZA.Outbox Overhead
Enqueue (1 message) 6.86 ยตs / 2.08 KB 6.99 ยตs / 2.13 KB +2% time, +2% alloc
Dispatch tick (10 messages) 105.4 ยตs / 11.9 KB 115.0 ยตs / 11.09 KB +9% time, โˆ’7% alloc

Near-zero abstraction overhead vs writing the same outbox by hand โ€” the 2โ€“9% delta is IOutboxWriter<T> + IOutboxStore interface dispatch. The value of ZA.Outbox is the [OutboxMessage] attribute + typed writer + ecosystem composability (resilience / telemetry / dispatcher bridges) at this cost.

Full methodology: docs/performance.md.

Features

Feature Notes
Source-generated writers [OutboxMessage] triggers generator; typed IOutboxWriter<T> emitted at compile time
Typed dispatchers IOutboxDispatcher<T> โ€” implement once, wire to any transport (bus, HTTP, email)
EF Core store Writes and reads via DbContext; enlist in ambient transaction for atomicity
InMemory store Thread-safe in-process store for unit and integration tests
Polling worker OutboxWorkerService (IHostedService) polls on configurable interval with scope isolation
Exponential backoff Retry delay = RetryBaseDelay ร— 2^(attempt-1); configurable via OutboxOptions
Dead-letter Entries that exceed MaxAttempts are dead-lettered with the failure reason
AOT / trimmer safe All dispatch code is generated; no Type.GetType, no MakeGenericType
IOptions<OutboxOptions> Full options support with hot-reload via standard Microsoft.Extensions.Options

Diagnostics

ID Severity Description
ZO0001 Warning [OutboxMessage] applied to an interface โ€” code will not be generated
ZO0002 Warning [OutboxMessage] applied to a static class โ€” code will not be generated
ZO0003 Warning [OutboxMessage] applied to a nested type โ€” use a top-level type for a stable type discriminator

Documentation

Full docs live in docs/:


License

MIT

Product Versions Compatible and additional computed target framework versions.
.NET net8.0 net8.0 is compatible.  net8.0-android net8.0-android was computed.  net8.0-browser net8.0-browser was computed.  net8.0-ios net8.0-ios was computed.  net8.0-maccatalyst net8.0-maccatalyst was computed.  net8.0-macos net8.0-macos was computed.  net8.0-tvos net8.0-tvos was computed.  net8.0-windows net8.0-windows was computed.  net9.0 net9.0 is compatible.  net9.0-android net9.0-android was computed.  net9.0-browser net9.0-browser was computed.  net9.0-ios net9.0-ios was computed.  net9.0-maccatalyst net9.0-maccatalyst was computed.  net9.0-macos net9.0-macos was computed.  net9.0-tvos net9.0-tvos was computed.  net9.0-windows net9.0-windows was computed.  net10.0 net10.0 is compatible.  net10.0-android net10.0-android was computed.  net10.0-browser net10.0-browser was computed.  net10.0-ios net10.0-ios was computed.  net10.0-maccatalyst net10.0-maccatalyst was computed.  net10.0-macos net10.0-macos was computed.  net10.0-tvos net10.0-tvos was computed.  net10.0-windows 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 (9)

Showing the top 5 NuGet packages that depend on ZeroAlloc.Outbox:

Package Downloads
ZeroAlloc.Outbox.EfCore

EF Core store adapter for ZeroAlloc.Outbox.

ZeroAlloc.Scheduling.EfCore

EF Core job store adapter for ZeroAlloc.Scheduling.

ZeroAlloc.Outbox.InMemory

In-memory store adapter for ZeroAlloc.Outbox (testing).

ZeroAlloc.Outbox.Telemetry

ZeroAlloc.Telemetry bridge for ZeroAlloc.Outbox โ€” wraps IOutboxTypeDispatcher with a source-generated OpenTelemetry proxy.

ZeroAlloc.Outbox.Dashboard

Operations dashboard for ZeroAlloc.Outbox. Minimal API + SSE + embedded HTML.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.5.0 600 5/14/2026
2.4.1 277 5/12/2026
2.4.0 586 5/4/2026
2.3.1 229 5/3/2026
2.3.0 210 5/1/2026
2.2.1 212 4/28/2026
2.2.0 136 4/28/2026
2.1.1 124 4/28/2026
2.1.0 141 4/26/2026
2.0.0 134 4/25/2026
1.3.0 138 4/25/2026
1.2.2 152 4/25/2026
1.2.1 557 4/24/2026
1.2.0 133 4/24/2026
1.1.2 139 4/23/2026
1.1.1 139 4/23/2026
1.1.0 139 4/22/2026
1.0.1 137 4/22/2026
1.0.0 145 4/20/2026
0.1.0 138 4/20/2026