PHPackages                             webrek/saga - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. webrek/saga

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

webrek/saga
===========

Orchestration-based sagas for PHP: run multi-step processes and roll them back with per-step compensations when one fails. Framework-agnostic core with an optional Laravel bridge.

v1.0.0(1mo ago)00MITPHPPHP ^8.2CI passing

Since Jun 29Pushed 1mo agoCompare

[ Source](https://github.com/webrek/saga)[ Packagist](https://packagist.org/packages/webrek/saga)[ Docs](https://github.com/webrek/saga)[ RSS](/packages/webrek-saga/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (10)Versions (2)Used By (0)

Saga
====

[](#saga)

[![Latest Version](https://camo.githubusercontent.com/3dab67061fc02765719fdf656e10aa22e4a7f1cf8220a19b50eaf5c48a7f8b48/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f7461672f77656272656b2f736167613f736f72743d73656d766572266c6162656c3d76657273692543332542336e267374796c653d666c61742d737175617265)](https://github.com/webrek/saga/releases)[![Tests](https://camo.githubusercontent.com/3cdd3b84a493aabd5074fa1881b79e3b530956b5b8ad3d6c9a3e5c72e316bec7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f77656272656b2f736167612f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/webrek/saga/actions/workflows/tests.yml)[![PHP](https://camo.githubusercontent.com/2195866c8c0e50a0cac338d708a9c7056b9681de027de3ac357d3fd4f93c55a2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e322d3737376262343f7374796c653d666c61742d737175617265)](https://php.net)[![License](https://camo.githubusercontent.com/b36f7c4bc633cd63ef426a3a0053919ef89fadfbb986d8d3452071516f6ee430/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f77656272656b2f736167613f7374796c653d666c61742d737175617265)](LICENSE)

Run **multi-step** processes and, if one fails midway, **undo the previous ones**through their compensation — in reverse order. The saga pattern, for when an operation touches several services and there's no database transaction that spans them all.

A **framework-independent core** (plain PHP) with an **optional Laravel bridge**(Eloquent journal, events, facade).

```
use Webrek\Saga\Laravel\Facades\Saga;
use Webrek\Saga\SagaContext;

$resultado = Saga::for('checkout', ['order_id' => 42])
    ->step('cobrar',
        fn (SagaContext $c) => $c->set('cargo', $pago->charge($c['order_id'])),
        compensate: fn (SagaContext $c) => $pago->refund($c['cargo']))
    ->step('apartar',
        fn (SagaContext $c) => $inventario->reserve($c['order_id']),
        compensate: fn (SagaContext $c) => $inventario->release($c['order_id']))
    ->step('enviar',
        fn (SagaContext $c) => $envios->create($c['order_id']))   // if this fails…
    ->run();

// …the inventory is released and the charge is refunded, automatically.
$resultado->isCompleted();   // false
$resultado->status;          // SagaStatus::Compensated
```

Completes webrek's **resilience quartet**: input ([idempotency](https://github.com/webrek/laravel-idempotency)) · output ([outbox](https://github.com/webrek/laravel-outbox)) · dependencies ([circuit-breaker](https://github.com/webrek/laravel-circuit-breaker)) · and **coordination** (this one).

Installation
------------

[](#installation)

```
composer require webrek/saga
```

On Laravel, the service provider is auto-discovered. Publish the journal migration:

```
php artisan vendor:publish --tag=saga-migrations
php artisan migrate
php artisan vendor:publish --tag=saga-config   # optional
```

How it runs
-----------

[](#how-it-runs)

Steps execute **in order**. A `SagaContext` (a bag of data) is passed to each step: what one step writes, the next — and the compensations — read.

If a step throws an exception, the already completed steps are **compensated in reverse order** and the saga ends with one of three statuses:

StatusMeaning`Completed`All steps ran successfully.`Compensated`A step failed and everything before it was undone cleanly.`CompensationFailed`A step failed **and** a compensation did too — left half-done, requires manual intervention.The result never swallows the original exception (`$resultado->failure`), and the `CompensationFailed` statuses are exactly the ones worth watching (`$resultado->needsAttention()`).

The journal (Laravel)
---------------------

[](#the-journal-laravel)

Every run is recorded in the `sagas` table: name, status, completed steps, context, the step that failed and compensation errors. It's your audit trail and, above all, the way to find the sagas whose compensation failed. Each run also dispatches an event (`SagaCompleted`, `SagaCompensated`, `SagaCompensationFailed`).

Disable it with `'journal' => false` in the configuration.

Without Laravel
---------------

[](#without-laravel)

```
use Webrek\Saga\{Saga, SagaRunner, SagaContext};

$saga = new Saga(new SagaRunner);   // no events, no journal
$resultado = $saga->for('checkout', ['order_id' => 42])
    ->step('cobrar', $accion, compensate: $compensacion)
    ->run();
```

For your own events or persistence, implement `Webrek\Saga\Contracts\EventDispatcher`and `Webrek\Saga\Contracts\SagaStore` and pass them to the `SagaRunner`.

Scope
-----

[](#scope)

This is a **synchronous, in-process orchestration** saga: it runs inside your request or your job. It's not a two-phase commit, and it doesn't retry steps on its own — if you need retries, combine it with Laravel's queue or with [webrek/laravel-circuit-breaker](https://github.com/webrek/laravel-circuit-breaker)inside a step. Compensations must be idempotent.

Testing
-------

[](#testing)

```
composer test
```

The core suite (`tests/Unit`) runs without a framework; the Laravel suite (`tests/Feature`) exercises the Eloquent journal.

Contributing
------------

[](#contributing)

See [CONTRIBUTING.md](CONTRIBUTING.md). Run `make check` before opening a pull request.

Security
--------

[](#security)

Report vulnerabilities through the [security advisory form](https://github.com/webrek/saga/security/advisories/new), not as public issues. See [SECURITY.md](SECURITY.md).

License
-------

[](#license)

The MIT License (MIT). See [LICENSE](LICENSE).

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance91

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7d8deca81629993819087597b5ad7695976b02e3d014f038e26e985f35f569de?d=identicon)[webrek](/maintainers/webrek)

---

Top Contributors

[![webrek](https://avatars.githubusercontent.com/u/5001338?v=4)](https://github.com/webrek "webrek (1 commits)")

---

Tags

compensationdistributed-transactionslaravelphpprocess-managerresiliencesagaphplaravelorchestrationprocess managerresiliencesagacompensationdistributed-transactions

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/webrek-saga/health.svg)

```
[![Health](https://phpackages.com/badges/webrek-saga/health.svg)](https://phpackages.com/packages/webrek-saga)
```

###  Alternatives

[amranidev/laracombee

Recommendation system for laravel

11539.8k1](/packages/amranidev-laracombee)[yieldstudio/tailwind-merge-php

Merge Tailwind CSS classes without style conflicts

4975.8k1](/packages/yieldstudio-tailwind-merge-php)[wujunze/money-wrapper

MoneyPHP Wrapper

103.8k](/packages/wujunze-money-wrapper)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
