complex-heart/domain-events
Domain events for Laravel: record and dispatch events directly from your domain models, then handle them with listeners to decouple business logic. Keeps entities clean, testable, and framework-light.
Architecture fit. complex-heart/domain-events targets the domain layer: it gives you primitives for recording events inside aggregates and a bus abstraction for publishing them, rather than a full event-sourcing framework. That is the right shape for a hexagonal or DDD-style Laravel codebase where the domain must stay free of framework imports (no Illuminate\* in entities). It complements, rather than replaces, Laravel's native event dispatcher: the domain records, an adapter publishes. If our architecture is "Laravel-first, models are the domain," the package adds a layer we will not use and the fit is poor.
Integration feasibility. MIT-licensed, Composer-installable, small public surface. The realistic effort is not in installing it but in writing the glue: a Laravel service provider binding, a bridge from the package's bus to EventDispatcher, transaction-aware dispatch (after-commit), and a listener registration convention. Budget 3–5 engineer-days for a spike plus adapter, not the "composer require" hour the README implies.
Technical risk. High, and concentrated in maturity rather than design. Signals: 0 stars, 0 dependents, a single maintainer, a release date of 2026-03-15 (i.e., effectively brand new), and an opportunity score of 34.35 — the problem space is already served by spatie/laravel-event-sourcing, EventSauce, Symfony Messenger, and Laravel's own events. Zero dependents means zero production battle-testing; we would be among the first to find the edge cases. Specific risks: pre-1.0 API churn, undocumented serialization contract, unclear PSR-14 compliance, no stated PHP/Laravel version matrix, no security policy.
Key questions for the maintainer (or our own spike).
Stack fit. Assumes PHP 8.1+ and a PSR-4 autoloaded codebase; framework-agnostic by design, so it slots into Laravel 10/11/12 only through an adapter we own. It is a fit for a modular monolith with explicit bounded contexts; a poor fit for a legacy CRUD app where "domain events" would be a rename of model observers.
Migration path. Do not retrofit. Pick one bounded context (billing, orders, onboarding) and introduce the package there, leaving existing Laravel events untouched. Where that context currently fires event(new OrderPlaced(...)) from a controller or observer, move the raise into the aggregate, keep the existing Laravel event as the outward-facing contract, and have the adapter translate. This gives a reversible seam: deleting the package's usage restores the status quo.
Compatibility. Verify before committing: PHP constraint vs. our runtime, whether the bus interface is PSR-14 (Psr\EventDispatcher\EventDispatcherInterface) or custom, and whether serialization uses __serialize, reflection, or manual toArray. If events must cross a queue or an outbox table, custom serialization is the single largest hidden cost — treat an unstable format as a blocker for async use.
Sequencing.
RecordsEvents trait + DomainEventBus. At this maturity level, in-house is a legitimate winner; the package must beat it on more than novelty.Maintenance. We should assume we own the code. Plan for a vendored fork or a pinned version with a documented patch queue; add it to the dependency review list with a named owner. A solo-maintainer package with no dependents is a bus-factor-1 dependency in our supply chain, and an abandoned release two years from now is the base case, not the tail risk.
Support. No community, no Stack Overflow corpus, no issue history to mine — every question is answered by reading source. Budget for internal documentation of the bus contract, event naming convention, and serialization format; that documentation is the actual deliverable, not the dependency.
Scaling. In-process, synchronous dispatch scales fine and is where this package is safest. Anything crossing a process boundary — queues, outbox, event store, projections — pushes work back onto us: delivery guarantees, idempotency keys, replay, schema evolution. Do not read "domain events" as "event-driven architecture"; the package supplies the vocabulary, not the reliability.
Failure modes to design against. Events dispatched before commit and then lost on rollback; duplicate delivery with no idempotency; deserialization breaking when a class is renamed or a property is removed; listener exceptions silently swallowed so a downstream projection drifts; event ordering assumptions violated once async is introduced.
Ramp-up. The API surface is small, so a mid-level engineer is productive in 1–2 days; the real cost is conceptual — aggregates, invariants, and why events are raised rather than fired from controllers. Expect one sprint of pairing for the pilot team plus a short internal brown-bag. Keep the blast radius at one bounded context until the adapter and the event catalog have survived a full release cycle.
How can I help you explore Laravel packages today?