Saga Lara Flow: Durable Workflows for Laravel | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. [Laravel](https://www.msaied.com/public/articles?category=laravel)
6. /
7. Saga Lara Flow: Durable Workflows and Compensating Transactions on Laravel Queues

   [Laravel](https://www.msaied.com/public/articles?category=laravel) [Composer Pacakge](https://www.msaied.com/public/articles?category=composer-pacakge) 

 Saga Lara Flow: Durable Workflows and Compensating Transactions on Laravel Queues
==================================================================================

 Saga Lara Flow is a Laravel package that lets you write long-running business processes as plain PHP methods on top of Laravel queues, with built-in compensating transactions, signals, parallel actions, and child workflows.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 7 Aug 2026 · Updated 7 Aug 2026 · 4 min read

ShareCopy linkCopied

 ![Saga Lara Flow: Durable Workflows and Compensating Transactions on Laravel Queues](https://cdn.msaied.com/520/d77bd3c0cecb6fb89c16f85648e7e369.png) 

  On this page +1. [What Is Saga Lara Flow?](#what-is-saga-lara-flow)
2. [Core Features at a Glance](#core-features-at-a-glance)
3. [Defining Workflows and Actions](#defining-workflows-and-actions)
4. [Compensating Failed Transactions](#compensating-failed-transactions)
5. [Signals: Waiting on External Input](#signals-waiting-on-external-input)
6. [Concurrency and Child Workflows](#concurrency-and-child-workflows)
7. [Installation](#installation)
8. [Key Takeaways](#key-takeaways)

 What Is Saga Lara Flow?
-----------------------

[Saga Lara Flow](https://github.com/discovery-ukraine/saga-lara-flow) is a Laravel package by Andriy Karpishyn that lets you model long-running business processes — charge a card, reserve stock, book a shipment — as a single `handle()` method on top of Laravel queues. No job chaining, no hand-rolled state machines.

The engine records every completed step to the database. When a worker picks up a workflow, it re-executes `handle()` from the top, but `$this->action()` intercepts each call: already-completed steps return their stored result instantly, and execution resumes only at the first unfinished step. If any step throws, registered compensations fire in reverse order.

Core Features at a Glance
-------------------------

- **Workflows as plain methods** — sequential `$this->action()` calls with no job chaining
- **Compensating transactions** — register an undo action per step with `compensateWith()`
- **Signals** — suspend a run until external input arrives, with optional timeout
- **Parallel blocks** — dispatch independent actions concurrently and collect results
- **Child workflows** — nest workflows with a configurable close policy
- **Side effect recording** — wrap non-deterministic values so replays stay deterministic
- **Tag-based querying** — find runs by workflow class, tag, and status
- **Artisan commands** — list, inspect, signal, cancel, prune, and monitor runs

Defining Workflows and Actions
------------------------------

A workflow extends `Workflow` and calls action classes through `$this->action()`. Actions are resolved from the container, so dependencies are injected automatically:

```php
use DiscoveryUkraine\SagaLaraFlow\Workflow;

class ProvisionAccountWorkflow extends Workflow
{
    public function handle(string $email): array
    {
        $tenantId = $this->action(CreateTenant::class, $email)->run();
        $this->action(SendWelcomeEmail::class, $email)->run();
        return ['tenant' => $tenantId];
    }
}

```

Runs are started via the `SagaFlow` facade. `runSync()` drives every step in-process, making it ideal for tests:

```php
$run = SagaFlow::create(ProvisionAccountWorkflow::class)
    ->withArguments('jane@example.com')
    ->runSync();

$this->assertTrue($run->isCompleted());

```

Non-deterministic values like UUIDs must be wrapped in `sideEffect()` so replays always see the original result:

```php
$reference = $this->sideEffect('reference', fn () => (string) Str::uuid());

```

Compensating Failed Transactions
--------------------------------

Each step can register an undo action. If a later step fails, compensations fire in reverse order:

```php
public function handle(string $orderId): void
{
    $this->action(ChargeCard::class, $orderId)
        ->compensateWith(RefundCard::class, $orderId)
        ->run();

    $this->action(ReserveStock::class, $orderId)
        ->compensateWith(ReleaseStock::class, $orderId)
        ->run();

    // If this throws, ReleaseStock runs first, then RefundCard.
    $this->action(ShipOrder::class, $orderId)->run();
}

```

For grouped rollbacks, `$this->saga()` supports `onCompensationFailure()` and `compensateInParallel()` to control whether a failed undo aborts the rollback and whether undos run concurrently.

Signals: Waiting on External Input
----------------------------------

`$this->signal()` suspends a run until external code delivers the named signal. `timeoutAfter()` adds a deadline:

```php
try {
    $decision = $this->signal('approval')
        ->timeoutAfter(now()->addDay())
        ->wait();
} catch (AwaitSignalTimeoutException $e) {
    $this->action(AutoReject::class)->run();
}

```

Deliver the signal from anywhere in your application:

```php
SagaFlow::loadFlow($runId)->signal('approval', ['approved' => true]);

```

Tag-based querying lets you locate the right run without storing its ID:

```php
SagaFlow::query()
    ->whereWorkflow(ProvisionCompanyWorkflow::class)
    ->whereTag('company', $companyId)
    ->signalable()
    ->handles()
    ->first()
    ?->signal('owner-synced');

```

Concurrency and Child Workflows
-------------------------------

Independent actions run in parallel with `$this->parallel()`:

```php
[$pricing, $inventory, $reviews] = $this->parallel()
    ->action(FetchPricing::class, $sku)
    ->action(FetchInventory::class, $sku)
    ->action(FetchReviews::class, $sku)
    ->run();

```

Child workflows are invoked with `$this->child()`, and a `ChildClosePolicy` controls what happens when the parent finishes.

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

The package requires **PHP 8.5** and **Laravel 13**:

```bash
composer require discovery-ukraine/saga-lara-flow
php artisan migrate
php artisan vendor:publish --tag="saga-lara-flow-config"

```

Register the expiration monitor with the Laravel scheduler:

```php
Schedule::command('saga-flow:monitor')->everyMinute();

```

Key Takeaways
-------------

- Write multi-step distributed processes as a single readable `handle()` method
- Automatic replay skips already-completed steps without re-running side effects
- Compensating transactions roll back completed steps in reverse order on failure
- Signals pause execution until a human or external system responds
- Parallel blocks, optional steps, child workflows, and versioning cover advanced use cases
- `runSync()` makes the whole workflow testable without a real queue

Full documentation is available at [sagalaraflow.dev](https://sagalaraflow.dev). Read the original announcement at [Laravel News](https://laravel-news.com/saga-lara-flow).

- [Laravel](https://www.msaied.com/public/articles?search=Laravel)
- [Workflows](https://www.msaied.com/public/articles?search=Workflows)
- [Saga Pattern](https://www.msaied.com/public/articles?search=Saga%20Pattern)
- [Queues](https://www.msaied.com/public/articles?search=Queues)
- [Compensating Transactions](https://www.msaied.com/public/articles?search=Compensating%20Transactions)
- [PHP Package](https://www.msaied.com/public/articles?search=PHP%20Package)

 Frequently asked questions 
---------------------------

  How does Saga Lara Flow avoid re-running completed steps when a workflow is replayed?The package records each completed step and its result to the database. On replay, `$this-&gt;action()` intercepts every call and returns the stored result for already-completed steps without executing the action class again. Execution only resumes at the first step that has not yet finished.

   What happens if a step in the middle of a workflow fails?When a step throws an exception, the engine triggers the compensation actions registered for all previously completed steps, running them in reverse order. You can register an undo action class or a closure per step using `compensateWith()`, and group compensations with `$this-&gt;saga()` for parallel or fault-tolerant rollback behavior.

   Can a workflow pause and wait for an external event like a human approval?Yes. `$this-&gt;signal()` suspends the workflow run and releases the worker. When external code calls `SagaFlow::loadFlow($runId)-&gt;signal('approval', $data)`, the run resumes from where it left off. You can also chain `timeoutAfter()` to set a deadline and catch `AwaitSignalTimeoutException` if it expires.

   ![Mohamed Said](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp)About the author
----------------

[Mohamed Said](https://www.msaied.com/public#person)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

[About](https://www.msaied.com/public#about) [GitHub ↗](https://github.com/EG-Mohamed) [LinkedIn ↗](https://www.linkedin.com/in/msaiedm/) [WhatsApp ↗](https://wa.me/201094619204) [Email Address ↗](mailto:hello@msaied.com) [My CV ↗](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)  

   [Previous articleFilament v4.12 &amp; v5.7: Major Performance Improvements and Security Patches](https://www.msaied.com/public/articles/filament-v412-v57-major-performance-improvements-and-security-patches) [Next articleEloquent Query Optimization: Slaying N+1 Problems at Scale](https://www.msaied.com/public/articles/eloquent-query-optimization-slaying-n1-problems-at-scale)  

   On this page
-------------

1. [What Is Saga Lara Flow?](#what-is-saga-lara-flow)
2. [Core Features at a Glance](#core-features-at-a-glance)
3. [Defining Workflows and Actions](#defining-workflows-and-actions)
4. [Compensating Failed Transactions](#compensating-failed-transactions)
5. [Signals: Waiting on External Input](#signals-waiting-on-external-input)
6. [Concurrency and Child Workflows](#concurrency-and-child-workflows)
7. [Installation](#installation)
8. [Key Takeaways](#key-takeaways)

 ###  Have a technical challenge?

 Tell me what you’re building. I reply within two working days.

[Start a conversation](https://www.msaied.com/public#contact) 

   Related articles
-----------------

 [ ![](https://cdn.msaied.com/740/cce86edc21eddcbdd2f2454fadaf9c70.png)  · 3 min read### The Pipeline Pattern in Laravel: Custom Pipelines Beyond Middleware

5 Oct 2026 ](https://www.msaied.com/public/articles/the-pipeline-pattern-in-laravel-custom-pipelines-beyond-middleware-1) [ ![](https://cdn.msaied.com/739/2d6897fdcdcf090613f96f72a64b8a78.png)  · 4 min read### MySQL Full-Text Search in Laravel: Indexes, Relevance Scoring, and Boolean Mode

4 Oct 2026 ](https://www.msaied.com/public/articles/mysql-full-text-search-in-laravel-indexes-relevance-scoring-and-boolean-mode) [ ![](https://cdn.msaied.com/738/073696a3fefe18bec825beec5ac658f5.png)  · 4 min read### Laravel Queue Rate-Limited Middleware: Throttling Jobs Without Losing Work

4 Oct 2026 ](https://www.msaied.com/public/articles/laravel-queue-rate-limited-middleware-throttling-jobs-without-losing-work) 

  Have a technical challenge?
----------------------------

Tell me what you’re building. I reply within two working days.

 [Discuss your project ↗](https://www.msaied.com/public#contact) 

  © 2026 Mohamed Said · Built with Laravel, meant to last.Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

 - [Home](https://www.msaied.com/public)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [GitHub](https://github.com/EG-Mohamed)
- [LinkedIn](https://www.linkedin.com/in/msaiedm/)
- [WhatsApp](https://wa.me/201094619204)
- [Email Address](mailto:hello@msaied.com)
- [My CV](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
- [Sitemap](https://www.msaied.com/public/sitemap.xml)
