Weave 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

Laravel Eventstore Laravel Package

digitalrisks/laravel-eventstore

A Laravel event store for event sourcing: persist domain events, rebuild aggregates from stored streams, and keep an auditable history of every change. Integrates with Laravel's database and service container.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require gosuperscript/laravel-eventstore, then publish the package config and migrations (php artisan vendor:publish --tag=eventstore-config / --tag=eventstore-migrations) and run php artisan migrate. The event store persists to a relational table, so decide up front whether it lives on your default connection or a dedicated one.
  • First place to look: config/eventstore.php (connection, table names, snapshot/projection settings) and the package README's "Aggregate" example. Everything else — projectors, reactors, replays — is a layer on top of the stored-events table.
  • First use case: pick one small, self-contained aggregate (e.g. Account with open/deposit/withdraw) and wire it end to end: record events on the aggregate, persist them, then rebuild the aggregate from its event stream and assert the state matches. Doing this before adding projectors catches serialization and versioning issues early.
  • Confirm the basics work before writing any domain code: write one event, read it back via the stored-event model, and assert the aggregate_uuid + aggregate_version ordering is what you expect.

Implementation Patterns

  • Aggregates as the write side. Keep aggregate methods free of I/O and side effects: they should validate intent and recordThat() a domain event. State changes belong in the apply* methods so that replaying the stream reconstructs the same object. Persist via the package's repository/EventStore facade rather than inserting rows yourself.
  • Projectors for read models. Build read tables from events rather than querying the event store for UI. Treat every projector as replayable: it must be idempotent (upsert by aggregate id, or delete-then-insert per aggregate) so projection:replay is safe.
  • Reactors for side effects. Emails, HTTP calls, and queue dispatches go in reactors, not projectors. Make reactors tolerant of duplicate delivery — at-least-once is the realistic guarantee.
  • Transactional boundaries. Wrap "append events + update the synchronous read model" in a single DB transaction when they share a connection; when they don't, accept eventual consistency and give the projector a position/checkpoint so it can resume.
  • Testing. Rebuild aggregates from in-memory event streams in unit tests (given/when/then), and only touch the database in integration tests. Assert on recorded events rather than on private state.
  • Integration tip: expose your write side through a thin command/service layer, and keep controllers calling that layer — this keeps the aggregate API the only entry point and makes replay/backfill tooling a matter of iterating the event table.

Gotchas and Tips

  • Connection loss is now a first-class failure (v8.4.1). The package throws ConnectionLostException instead of a plain Exception when the store connection drops (issue #33). Import and catch that type explicitly in long-running consumers (queue workers, reactors, console replay commands) so you can reconnect and retry rather than letting the job die. Because it still extends Exception, existing broad catch (\Exception $e) blocks keep working — which means you may not notice the change; audit those catch blocks and narrow them where retry semantics matter. Note the changed type in any instanceof checks or exception-mapping middleware.
  • Catch-all handlers hide retryability. After upgrading, ensure your queue job's failed()/retryUntil() and any global exception handler distinguish connection loss (retryable) from domain/validation failure (not retryable). A dropped connection should never be recorded as a permanent failure.
  • Long-lived processes go stale. Console projectors and workers hold a connection for the whole run; configure a sane DB::reconnect() or rely on the new exception to detect and recover.
  • Version numbers are your concurrency control. Two processes appending to the same aggregate must collide loudly (unique index on uuid + version). Don't disable it for convenience — surface it as a retryable conflict instead.
  • Serialization is where event sourcing breaks. Value objects, enums, and dates must round-trip through the payload. Test a full write → replay cycle for every new event class, and version payloads (event_version) the moment you need to change a field. Never mutate a released event's shape in place.
  • Don't rename aggregate/event classes casually. Stored events reference class names in the payload; a rename silently breaks replay. Add an upcaster or an explicit alias map.
  • Projection drift is silent. Keep a position/checkpoint column and a projection:status-style command; a projector that quietly stops advancing looks identical to one with nothing to do.
  • Snapshots are an optimization, not a source of truth. Introduce them only after stream length becomes a measured problem, and make snapshot invalidation explicit when event schemas change.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core