Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Transactional Outbox Laravel Package

urfysoft/transactional-outbox

Laravel package implementing the Transactional Outbox pattern for microservices: store outbound events in a DB outbox, process and dispatch reliably (HTTP driver; Kafka/RabbitMQ planned), handle inbound inbox events with idempotent handlers, and secure calls via Sanctum abilities.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install & publish assets
    Run composer require urfysoft/transactional-outbox, then php artisan vendor:publish --provider="Urfysoft\TransactionalOutbox\TransactionalOutboxServiceProvider" to get config and migrations. Run php artisan migrate immediately after.

  2. Configure Sanctum first
    Since the package relies on Sanctum for service-to-service authentication, ensure Sanctum is installed (laravel/sanctum) and migrated. Set up tokens with the configured ability (default transactional-outbox) for downstream services.

  3. First use case: Atomic event publishing
    Wrap business logic and message dispatch in one transaction using OutboxService::executeAndSend(). For example, in OrderController, create an order and emit OrderCreated atomically—guaranteeing no orphan messages even if the broker fails.

Implementation Patterns

  • Atomic Business Logic + Message Dispatch
    Always use executeAndSend()/executeAndSendMultiple() to wrap domain logic and outbox creation in the same DB transaction—never emit events after transaction commit.

  • Outbox Service Abstraction
    Inject Urfysoft\TransactionalOutbox\Services\OutboxService (or use TransactionalOutbox facade) into your service layer or controllers. Prefer constructor injection for testability.

  • Inbox Handler Organization
    Register handlers either via config/transactional-outbox.php (static) or runtime via TransactionalOutbox::registerInboxHandler(). Group handlers by domain (e.g., App\Messaging\Order\*, App\Messaging\Payment\*) and keep handle() methods lightweight—delegate heavy work to queued jobs.

  • Webhook Endpoint Setup
    Create a single /api/webhooks/messages endpoint that delegates to the package’s built-in inbox processing. Ensure external services send required headers: X-Message-Id, X-Source-Service, X-Event-Type, and X-API-Key.

  • Driver Flexibility
    Start with HTTP driver (zero infrastructure), then migrate to Kafka/RabbitMQ by installing the dependency and updating MESSAGE_BROKER_DRIVER. Avoid premature complexity—HTTP suffices for most small-to-mid services.

Gotchas and Tips

  • Scheduler is mandatory
    Background processing requires php artisan schedule:work (typically run via cron). Manual outbox:process is for debugging only—avoid in production. Verify cron entries with php artisan schedule:run.

  • Inbox deduplication depends on message_id
    If external services reuse X-Message-Id, duplicates may bypass idempotency. Enforce strict uniqueness across producers (e.g., UUIDv7 + source timestamp).

  • Failed messages persist—monitor them!
    Failed outbox/inbox messages remain in DB indefinitely. Query last_error and set up alerts (e.g., COUNT(*) WHERE status='failed' AND updated_at < NOW() - INTERVAL 5 MINUTE). Use messages:cleanup only after final retries.

  • Sanctum token scope matters
    Incoming requests must include a Sanctum token with exactly the configured sanctum.required_ability. Test with curl -H "Authorization: Bearer <token> ...". Ensure tokens are scoped per service—avoid shared tokens.

  • Avoid payload bloat
    The package does not truncate payloads—small payloads (<1MB) recommended. Prefer sending IDs and fetch related data on consumption, or compress for large payloads (if using custom driver).

  • Extension points: Custom drivers
    Implement Urfysoft\TransactionalOutbox\Contracts\BrokerDriver to support non-listed brokers (e.g., SQS, Pulsar). Override getDriver() in OutboxService or extend the service class.

  • Dead-letter strategy
    After max retries, move messages to a DLQ (e.g., separate DB table or external queue). Implement custom cleanup logic in a scheduled job—this package doesn’t auto-DLQ by default.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport