landingi/event-store-bundle
A PHP event store bundle that adds event sourcing infrastructure to your application: append domain events to streams, replay them to rebuild aggregates, and wire the store into your existing framework services with minimal configuration.
Architecture fit
The package name and conventions (*-bundle, Landingi's Symfony-based stack) indicate a Symfony bundle, not a Laravel package. That distinction drives most of this assessment: bundles rely on Symfony's kernel, DI extension classes (DependencyInjection/*Extension.php), compiler passes, and tag-based service discovery. Laravel has no equivalent lifecycle, so "install and register" will not work out of the box — you would be consuming the underlying event-store library directly and hand-wiring its services into Laravel's container.
Functionally, an event store is an append-only persistence layer for domain events with stream/aggregate identity, optimistic concurrency, and (typically) projection support. That is a legitimate architectural fit only if the product genuinely needs event sourcing — audit-grade history, temporal queries, replayable read models, multiple projections over the same facts. If the requirement is "audit log plus a few notifications," a table plus observers is cheaper and safer. Event sourcing is a one-way door for the domain model; the TPM decision is not "which event store library" but "do we adopt event sourcing at all."
Integration feasibility
Composer installation is trivial; runtime integration is the work. Expect to write: a Laravel service provider binding the store's interfaces, config translation (Symfony tree config → Laravel config/*.php), DBAL/connection bridging if the store speaks Doctrine rather than Eloquent, and an adapter so domain code depends on our interface rather than Landingi's classes. Feasible, but it is a bespoke adapter project, not a dependency add.
Technical risk
by_support implementation and ships it as a minor version bump (2.1.0 → 2.2.0). Removing a feature is a breaking change by semver's own definition and should have been 3.0.0. A composer update with a ^2.2 constraint can therefore silently delete a capability you depend on. This is the clearest evidence yet that upstream treats the public API as private: version numbers track their release train, not consumer contracts.DIS-54) and PR #27, with no deprecation notice, no migration note, and no statement of what replaces by_support (if anything). There was no announced deprecation window. Consumers must read the diff to learn what broke.by_support query surface tells us the store exposes non-trivial read/filter APIs that we have no documentation for.symfony/* ranges that conflict with the framework's constraints, composer update becomes a negotiation. This is the most likely immediate blocker.Key questions
composer.json requirements — PHP version, Symfony ranges, Doctrine DBAL version, PDO drivers?by_support do, what replaces it, and does anything we would build depend on it? Read PR #27's diff before answering.Stack fit
Works if: PHP 8.1+, Laravel 10/11/12, MySQL 8 or PostgreSQL (Postgres preferred for JSONB and better append concurrency), and a queue (Redis/SQS) for asynchronous projections. It does not fit a team that wants Eloquent-native models end to end — event stores bypass the ORM by design, so your read side will be hand-built or projection-table based.
Migration path
composer.json and the DI extension, attempt composer require in a throwaway Laravel app. Success criterion: append an event and read it back. Read the v2.1.0 → v2.2.0 diff (PR #27) as part of the spike — it is a small, high-signal probe of upstream's code quality and change discipline.App\EventStore\{Store, StreamId, RecordedEvent} interfaces owned by us; implement with Landingi's library. This keeps the vendor swappable and makes the "we chose wrong" cost a single class rewrite. It is also your insulation against silent API removal.Compatibility
Confirm before committing: Laravel's Symfony component versions vs. the bundle's constraints; whether Doctrine DBAL is a hard dependency (it usually is for these stores) and whether you accept DBAL alongside Eloquent; whether the store can share the app's existing DB connection or demands its own.
Dependency policy (revised)
Given v2.2.0, do not float the constraint. Pin to an exact version (2.2.0, or 2.1.x if you rely on by_support), and treat every upgrade as a reviewed change: read the PR diff, run the consumer test suite, and stage through a non-production environment. ^2.2 is not a safe constraint for this package.
Sequencing
Spike (including diff review) → adapter interfaces → pin + fork → pilot on a single bounded context with real audit requirements (billing, entitlements, or compliance-sensitive state) → production read model + projection worker → expand. Do not start with the core domain model.
Alternatives to weigh in the same spike: spatie/laravel-event-sourcing (Laravel-native, maintained, opinionated), patchlevel/event-sourcing (framework-light, actively maintained), or a pragmatic domain_events table. Choose Landingi's only if the spike shows a materially better storage/concurrency design — otherwise you are paying integration cost for a package that has now demonstrated it will break you on a minor release.
Maintenance
Ongoing cost is real and recurring, and v2.2.0 raises it: pinning versions, carrying a fork, and reviewing every upstream release diff by hand because changelogs are auto-generated one-liners with internal ticket references and no deprecation or migration guidance. Two releases in a short window (previous 2025-10-20, then v2.2.0) is a healthy cadence for them and a review burden for us. Assign explicit ownership — a named engineer, not "the platform team." Add the fork and the pinned version to your dependency-review checklist alongside any other single-maintainer dependency.
Support
No SLA, no public issue triage, no docs beyond the package itself. The v2.2.0 changelog confirms this pattern: change rationale lives in an internal Jira (DIS-54) we cannot read. Escalation is a direct email to a commercial partner who has no contractual reason to respond. Treat support as "self-service with optional goodwill." If a business relationship with Landingi exists, formalize a channel; if not, assume none.
Scaling
Event stores scale on the write side but strain elsewhere: append volume and table growth (plan partitioning or archival from day one), projection lag under queue backlog, and rebuild time that grows linearly with history — snapshots become mandatory past a few thousand events per aggregate. Concurrency conflicts surface as user-facing retries; design the UX for that before launch, not after.
Failure modes
composer update can remove a code path in production.Ramp-up
Two to three weeks of genuine learning curve for engineers new to event sourcing — and the concepts, not the library, are the hard part. Plan for a short internal design review, written conventions for event naming and versioning, and observability (append counts, projection lag, conflict rate, replay duration) instrumented in the pilot rather than retrofitted. Add one hour of onboarding per engineer on our pinning/fork/upgrade workflow — that process is now a required competency.
TPM recommendation: proceed only if the spike passes and event sourcing is a confirmed architectural requirement — and only with an exact version pin and a fork we control from day one. v2.2.0 removes a public capability on a minor version bump with no deprecation path and no migration note; that is the behavior of an internal artifact, not a dependency you can lean on. Score the package as low-traction infrastructure with unmanaged API stability: viable as a foundation we own, not as a dependency we consume.
How can I help you explore Laravel packages today?