outbox-pattern

Implements transactional outbox messaging with retry, dead-letter, and idempotent dispatchers.

7|3|Updated Sep 23, 2025
One-click install
npx skills add https://github.com/islamu-ngo/Event --skill outbox-pattern-islamu-ngo
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: outbox-pattern
Source: https://github.com/islamu-ngo/Event/tree/main/.agents/skills/outbox-pattern
Command: npx skills add https://github.com/islamu-ngo/Event --skill outbox-pattern-islamu-ngo

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? It prevents lost events and dual-write failures when a database commit and an external message dispatch must happen atomically, by persisting events to an outbox table and delivering them asynchronously with at-least-once guarantees. ## Core Features & Use Cases - Transactional Outbox Entity: Defines the OutboxMessage entity with UUID v7 IDs, JSONB payloads, and a Pending/Processing/Completed/Failed/DeadLettered status lifecycle. - Polling Processor with Backoff: Configures an OutboxProcessor background service using PeriodicTimer polling, optimistic concurrency claims, and exponential retry with a configurable ceiling. - Specialized Variants: Documents three independent outbox tables (general OutboxMessage, PolicyChangeOutbox, PdsSyncOutbox) each with dedicated entities and repositories. - Use Case: When publishing a domain event like EventCreated after saving an aggregate, write it to the outbox in the same transaction and let the processor dispatch it reliably, surviving crashes and duplicate deliveries. ## Quick Start Ask the AI to implement a new domain event using the transactional outbox pattern with an idempotent dispatcher and retry handling.

Frequently Asked Questions about outbox-pattern

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I implement the transactional outbox pattern in .NET?▼

Save an OutboxMessage row in the same transaction as your aggregate changes, then run a background OutboxProcessor that polls pending messages and dispatches them via IOutboxMessageDispatcher. Use optimistic concurrency in TryMarkAsProcessing so multiple processor instances do not double-claim messages.

How does outbox retry and dead-letter handling work?▼

Failed dispatches increment RetryCount and schedule NextRetryAt using exponential backoff: InitialRetryDelaySeconds times 2^retryCount, capped at MaxRetryDelaySeconds. After MaxRetries is exhausted, the message transitions to DeadLettered and remains in the database for monitoring.

Why must outbox message dispatchers be idempotent?▼

The outbox pattern guarantees at-least-once delivery, so the same message can be dispatched multiple times after crashes or contention. Dispatchers must deduplicate by message ID or use upserts and conditional writes to make repeated delivery safe.

When should I not use the outbox pattern?▼

Skip it for synchronous in-process events with no external side effect, where a simple domain event dispatcher suffices. The outbox adds a table, polling worker, and retry machinery that is only justified when delivery must survive failures.

Does the outbox processor poll or react to events?▼

The OutboxProcessor polls on a PeriodicTimer with a default interval of 5 seconds, fetching batches of Pending messages whose NextRetryAt is null or past. It is not event-driven, which keeps delivery independent of the write path.