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

Broadway Saga Laravel Package

broadway/broadway-saga

Experimental Broadway component that adds saga support to your application, offering saga state and metadata management plus a manager for waking up and starting sagas. Proof-of-concept and highly experimental, so intended for early exploration rather than production use.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Bottom line: This is a proof-of-concept, explicitly labelled "highly experimental," and the repository is archived. A TPM should treat it as a reference architecture, not a dependency. The realistic leverage is design influence — its saga state/metadata model and its "manager that wakes and starts sagas" are worth copying into a small in-house Laravel package built on maintained primitives. Adopting broadway/broadway-saga directly into a production Laravel codebase should be rejected unless the application is already a committed Broadway event-sourcing shop, and even then the archive status is disqualifying without a funded fork.

Architecture fit

  • The package is a thin layer over Broadway: it manages saga state and metadata and provides a manager to wake up and resume sagas. It is not a workflow engine; it has no scheduler, no retry policy, no compensation engine, and no transport. Those are yours to build.
  • It presupposes Broadway's DomainMessage pipeline (the 0.9 breaking change moved saga handlers from raw events to DomainMessage). That means the app needs a Broadway CommandBus, event store, and event stream — a second persistence and dispatch stack living beside Eloquent, Laravel's queue, and Illuminate\Events.
  • Fit is good only for teams already on CQRS/event sourcing with Broadway. For an Eloquent-centric Laravel app, adopting Broadway in order to get sagas is a large architectural commitment to acquire roughly 1–2k lines of bookkeeping.
  • Persistence is a separate concern: MongoDB state persistence was split out into broadway/saga-state-mongodb in 0.4.0. There is no first-party relational/Eloquent state store, which is a real gap in a MySQL/Postgres Laravel estate.

Integration feasibility

  • Zero Laravel ergonomics: no service provider, no package auto-discovery, no config file, no facade, no Artisan commands. All wiring is manual — implement SagaState, a state repository, a saga-state factory, register saga types with the manager, then feed DomainMessages in.
  • Composer constraint risk is the practical blocker. The package pins broadway/broadway ^2.3.1 and was last released in the PHP 7.x era (0.7.0 required PHP ≥ 7.1, 0.8.0 PHP ≥ 7.2). Modern Laravel (10/11/12) requires PHP 8.1+, and transitive PHP/Doctrine DBAL constraints will fight composer update; expect --ignore-platform-reqs hacks, which are a supply-chain smell.
  • The published metadata says "last release 2026-08-09" alongside "Archived: yes" and 0 dependents. Treat the freshness signal as unreliable and the archive flag as authoritative — no releases mean no downstream patch path.

Technical risk

  • Abandonment risk: high, and already realised. Archived, 35 stars, 0 dependents. No security response, no PHP 8.3/8.4 compatibility commitment, no Laravel compatibility matrix. Every future framework or PHP upgrade becomes an internal patch project.
  • API instability risk: high. Still 0.x, with a breaking handler-signature change at 0.9.0. "Highly experimental" in the README is an accurate contract.
  • Correctness risk: high, and the library does not absorb it. Sagas fail on non-idempotent handlers, duplicate delivery, out-of-order events, and non-compensable steps. The package gives you persistence of state, not the guarantees. Teams routinely underestimate this by a full quarter.
  • Coupling risk: medium-high. You inherit Broadway's CommandBus, EventStore, and DomainMessage vocabulary; unwinding later means rewriting handlers and re-homing state.

Key questions to put to the team

  1. Are we already running Broadway in production? If no, what is the business case for adopting it solely for sagas?
  2. Which saga state store do we use? MongoDB-only is likely a blocker; if we need SQL, who writes the state repository, and who owns it?
  3. What is our PHP/Laravel upgrade cadence, and who owns forking this package when the next PHP minor lands?
  4. What are our idempotency and compensation guarantees, and how will we test them (fault injection, duplicate-delivery tests)?
  5. Where does saga progress surface in Horizon/Sentry/logging today, given there is no built-in integration?
  6. Have we evaluated maintained alternatives — laravel-workflow, a Temporal PHP SDK, Symfony Workflow for state, or spatie/laravel-event-sourcing projectors — before taking on an archived PoC?
  7. Who is the named code owner if we fork, and what is the acceptable CVE-patch SLA for a component we now maintain?

Integration Approach

Stack fit

  • Green light: an existing Broadway + Doctrine DBAL + MongoDB estate, where this is additive and a fork is already budgeted.
  • Yellow light: a Laravel app that has adopted Broadway for a bounded domain; use it behind an internal interface so the dependency never leaks.
  • Red light: an Eloquent-only Laravel app. Recommend not adopting the package. Instead lift its concepts — saga identity, state record, metadata, a resumption manager — into ~300–500 lines of first-party code using Eloquent + queued jobs + Laravel's Context/logging. That captures the value with none of the archive risk.

Recommended path (red/yellow light): port the pattern, not the package

  1. Spike (1 week): stand up the package in a throwaway branch against our actual PHP/Laravel versions. Success criterion is composer require resolving without platform overrides and one saga resuming from persisted state. Expect this to fail; the failure is the deliverable.
  2. Extract the model: define SagaState (id, type, status, state payload, metadata, timestamps, version) and a SagaManager contract in our own namespace. Mirror the package's semantics so any future swap is mechanical.
  3. Implement on Laravel primitives: Eloquent state table, queued WakeSaga/AdvanceSaga jobs, Illuminate\Events subscriptions keyed by saga correlation ID, DB transaction around state transitions with optimistic-lock versioning.
  4. Harden: idempotency keys on all handlers, explicit compensation handlers per step, dead-letter queue for exhausted sagas, timeout sweeper command.
  5. Decommission the spike: delete the broadway/* dependency; keep the design doc and tests.

Alternative path (green light): fork-and-pin

  • Fork to internal/broadway-saga, pin exact upstream SHA, add a Laravel service provider and config, and publish the Mongo state store requirement as an ADR. Assign a code owner and a re-review trigger on every PHP minor.

Compatibility matrix

Laravel capability Compatibility Note
Service providers / container Manual No auto-discovery; bind CommandBus and the saga manager yourself
Eloquent ORM ❌ Broadway persists via Doctrine DBAL; state store is a separate Mongo package
Illuminate\Queue / Horizon ⚠️ Coexists, but Broadway workers are invisible to Horizon unless you instrument them
Illuminate\Events ✅ Broadway events can be bridged; watch for double-dispatch
PHP 8.2–8.4 ⚠️/❌ Last constraints target PHP 7.x; verify or patch
Observability ❌ No OpenTelemetry/Sentry hooks; custom logging required

Sequencing (if proceeding)

  1. ADR + spike outcome; explicit go/no-go gate with a named owner.
  2. Abstraction seam (SagaManager interface) committed before any vendor code, so exit is cheap.
  3. State store decision (SQL vs Mongo) — this, not the saga logic, is the long pole.
  4. One non-critical saga end-to-end in staging, including forced compensation and duplicate-delivery tests.
  5. Production with a single saga; monitor for one full business cycle before a second.
  6. Only then consider retiring any existing hand-rolled compensating logic.

Operational Impact

Maintenance

  • Archived means we are the maintainers from day one. Budget a fork, a CODEOWNERS entry, a private registry entry, and a documented patch process.
  • Dependency drift is the recurring cost: every PHP minor and every Laravel major is a potential internal patch. With 0 dependents and no upstream releases, we will be the only organisation validating compatibility — there is no common-mode failure to hide behind.
  • Debugging cost is materially higher than CRUD: a failed saga spans several commands, events, and persisted state rows. Teams routinely under-invest in saga-level tracing and pay for it in incident minutes.

Support

  • No vendor, no SLA. "Community-driven" with 35 stars and no dependents effectively means self-support.
  • Documentation is README-plus-changelog; the changelog is a commit list, not guidance. Onboarding material must be written internally.
  • Two-role coverage minimum: at least two engineers able to read Broadway's event store and reason about compensation. Single-owner sagas are an availability risk.

Scaling

  • The saga manager wakes and starts sagas; how it is triggered (cron sweeper vs. event-driven) determines your latency profile and your idle cost. A polling sweeper on a busy event stream is a hidden tax that does not appear in load tests.
  • State-store throughput and growth are the scaling ceiling, not compute: every saga transition is a write with concurrency control. Plan for indexing on saga id and status, and for archival/retention of completed sagas.
  • Long-running sagas pin worker capacity and interact badly with queue retry_after and job timeouts. Set saga-level timeouts explicitly rather than inheriting queue defaults.

Failure modes to design for, explicitly

  • Stuck saga: handler consumed the event, state write failed. Needs a reconciler, not just retries.
  • Poison saga: compensation handler itself fails; without a dead-letter and manual replay tool this becomes a paged incident with no runbook.
  • Double compensation: at-least-once delivery plus non-idempotent compensation equals duplicated refunds or duplicated provisioning. This is the single most expensive failure class and must be tested, not assumed.
  • Orphaned state: saga types renamed or deregistered leave unrecoverable rows. Version saga types from day one.
  • Silent backlog: no Horizon visibility means failing sagas look like a quiet queue. Emit a gauge for sagas in non-terminal states older than N minutes, and alert on it.
  • Metadata skew: the repository reports both a 2026 release and archived status. Distrust the freshness signal and build the upgrade decision on the archive flag.

Ramp-up

  • Broadway/event-sourcing literacy is the gate: assume 3–6 weeks before an engineer is productive on saga debugging, and longer for on-call confidence. That training cost is paid whether you adopt the package or only borrow its pattern — which is all the more reason not to also pay the maintenance cost of an archived dependency.
  • Ship a one-page saga runbook (how to find a saga, how to inspect state, how to replay, how to disable) before the first production saga. If we cannot write that runbook, we should not ship the saga.
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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin