eventsauce/message-outbox
Laravel package that adds an outbox to EventSauce message dispatching, helping you store outgoing messages and publish them reliably. Useful for preventing lost events in async workflows and supporting at-least-once delivery.
Event-Driven Alignment: The package implements the Message Outbox pattern, which is a critical component for event sourcing and CQRS architectures. It ensures reliable event publishing by decoupling event generation from persistence, reducing the risk of lost events during failures.
Laravel Compatibility:
eventsauce/backoff for retry logic on failures.database or redis queues) to replace polling.| Risk Area | Severity | Mitigation Strategy |
|---|---|---|
| Database Schema Changes | High | Requires manual outbox table setup; migrations must be idempotent. |
| Polling Overhead | Medium | Replace with Laravel queues for better scalability. |
| EventSauce Dependency | High | Abstract EventSauce-specific logic if using Laravel’s event system. |
| Transaction Isolation | Medium | Ensure outbox operations are in the same transaction as domain logic. |
| Monitoring Gaps | Medium | Add Laravel Scout or custom metrics for outbox health. |
Why Event Outbox?
Database Schema
Polling vs. Real-Time
Error Handling & Retries
Testing Strategy
| Component | Laravel Native Alternative | Integration Strategy |
|---|---|---|
| Event Publishing | Laravel Events + Queues | Use Laravel queues as the transport layer; adapt outbox to store queue jobs. |
| Polling Worker | Laravel Queue Workers | Replace polling with php artisan queue:work. |
| Retry Logic | Laravel Queue Retries | Configure backoff to match Laravel’s retry settings. |
| Database | Laravel Migrations | Define outbox table via Laravel migrations. |
| Event Sourcing | Custom Event Store (e.g., Doctrine) | Abstract EventSauce if using Laravel’s event system. |
Phase 1: Schema Setup
Schema::create('message_outbox', function (Blueprint $table) {
$table->id();
$table->string('message_type');
$table->text('message');
$table->timestamp('occurred_at')->useCurrent();
$table->timestamp('published_at')->nullable();
$table->index(['published_at', 'message_type']);
});
Phase 2: Event Publishing
// Instead of:
// event(new OrderPlaced($order));
// Use:
$outbox = app(MessageOutbox::class);
$outbox->store(new OrderPlaced($order));
Phase 3: Worker Integration
php artisan queue:work --queue=outbox
Phase 4: Testing & Validation
published_at for delayed events; investigate worker logs.message_type if sharding is needed.| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Database Outage | Lost events | Use a write-ahead log (WAL) or replicate outbox. |
| Worker Crash | Unpublished events | Enable queue retries and alerts. |
| Schema Migration Failure | Broken outbox table | Use Laravel’s rollback migrations. |
| Event Consumer Failures | Poison pills in outbox | Implement dead-letter queues. |
| Network Partition (Pub/Sub) | Events not delivered | Use Laravel’s queue retry logic. |
User).How can I help you explore Laravel packages today?