Product Decisions This Supports
- Adopt-or-not decision on CQRS as the internal structure for a bounded context. The package is an implementation detail, but choosing it (or not) forces the real product decision: whether each use case becomes an explicit Command/Query + Handler pair rather than a method on a service class. That changes how features are estimated, reviewed, and parallelized.
- Build vs. buy for dispatch infrastructure. Rolling your own handler-resolution and command/query contracts is 1–3 days of work plus ongoing ownership. A small, MIT-licensed base package replaces that with a dependency — a real trade to make explicitly rather than by default.
- Roadmap sequencing for incremental migration. Because CQRS adoption can be done one use case at a time, this supports a "new features in handlers, legacy code untouched" roadmap line rather than a big-bang rewrite. That is the main reason to pick a thin base package over a full framework.
- Where cross-cutting product requirements get attached. Audit trails, transactional boundaries, authorization checks, idempotency for retried operations, and offloading slow work to queues are all natural bus/middleware concerns. Committing to a dispatcher shape is effectively committing to where compliance and reliability features will live — a decision worth making before those requirements land, not after.
- Scoping of "use case" as the unit of delivery. Handlers give a one-to-one mapping between a product-facing capability and a unit of code, which makes prioritization, ownership, and per-feature instrumentation (metrics, tracing) tractable. Useful when the team is scaling and you need clean seams for parallel work.
- Framework-upgrade risk as a roadmap input. Version 2.3.0 adds Symfony 8 support, so the package currently tracks the upstream components Laravel itself builds on. That means adopting it does not pin the platform upgrade path today — a relevant input when scheduling the next Laravel major upgrade, and a signal to re-check on each release rather than a one-time fact.
- Buy-in on team topology and onboarding cost. If handlers are the interface, new engineers can be pointed at a single class per capability. This is a hiring/onboarding argument as much as an architectural one.
When to Consider This Package
Consider it when:
- You are on Laravel/PHP and want only the base contracts — command/query marker types, handler interfaces, and a resolver — without pulling in a full messaging framework.
- You already intend to adopt CQRS in at least one bounded context and want the conventions fixed rather than debated per-sprint.
- The dependency stays shallow and wrapped: your application code depends on your own
CommandBus/QueryBus interfaces, with this package as one adapter behind them. That makes the adoption reversible, which is the only thing that makes a 1-star package defensible.
- You want a low-ceremony option you can read end-to-end in an afternoon, rather than a framework with its own learning curve.
- You are approaching or already on a Symfony 8 component baseline. 2.3.0 explicitly supports it, so there is no compatibility gap to work around. Nothing in the release changes the package's surface — it is a compatibility bump, not a feature or a breaking change — so the assessment carries forward unchanged.
Look elsewhere when:
- You need asynchronous transport, retries, scheduling, sagas/process managers, or event sourcing. Reach for Symfony Messenger, Ecotone, or Laravel's queue-backed bus instead — this package is not that, and stretching it there is a rebuild.
- You need vendor assurance: SLA, security response commitments, a maintainer you can call, or a broad hiring pool familiar with the API. With 1 star and 0 dependents there is effectively no community, no third-party documentation, and no evidence of production use outside the maintainer's own estate. That is a genuine, quantified risk — not a stylistic objection. The 2.3.0 release is evidence the maintainer is still shipping, but it is one maintainer either way: bus-factor 1 is unchanged.
- Your team is not already fluent in CQRS. The abstraction will not teach the pattern, and a misunderstood pattern is more expensive than a fat service class.
- Your domain is small or CRUD-shaped. The indirection will cost more in code volume and review time than it returns.
- Recommended framing regardless: treat this as a spike candidate, not a platform commitment. Time-box an evaluation against one real feature, confirm the maintenance signal — release cadence looks active and now spans Symfony 8 compatibility (a 2026 release date, routine upstream tracking) — but a single maintainer and zero dependents still means bus-factor 1 — and keep it behind your own interfaces.
How to Pitch It (Stakeholders)
To executives — one paragraph: This is a small, free (MIT) library that standardizes how we structure business logic in our Laravel applications, so each product capability lives in one clearly named, independently testable place. The upside is delivery predictability: new features follow a repeatable shape, cross-cutting requirements like audit logging and authorization attach in one location instead of scattered across controllers, and we can modernize legacy code one feature at a time instead of via a risky rewrite. The cost is one dependency and a short learning curve. The risk is that the library still has negligible public adoption (1 star, no downstream users) and a single maintainer — the latest release keeps it compatible with current Symfony components, which is a good maintenance signal but does not change the bus-factor-1 exposure — so the recommendation is to adopt it only behind our own interfaces, which caps the cost of replacing it at a few days. Ask: approve a two-week spike against one real feature, with a go/no-go before it touches anything customer-facing.
To engineering — the substance: It provides base contracts for commands, queries, and their handlers plus resolution. It is deliberately thin — that is the point and also the limit. It does not give you async dispatch, middleware pipelines you don't write, retries, or event sourcing; if those appear on the roadmap, plan for Symfony Messenger or Ecotone and treat this as a stopgap. 2.3.0 is a compatibility-only release adding Symfony 8 support — no new API, no deprecations, no migration work — so it changes nothing in your integration but confirms we are not adopting something that already lags the framework. Do not let application code type-hint against it directly: define our own bus and handler interfaces, adapt this behind them, and the swap-out cost stays bounded. Evaluate it on measurable criteria — lines of glue code saved, test ergonomics for a handler, and how it behaves under our existing DI and transaction setup — and report back before we standardize.