All use cases
Automation

Run long workflows that survive a deploy

Per-node checkpointing, so a killed worker does not redo side effects.

The problem

A long automation runs inside one job. Halfway through, the worker is killed — a deploy, a timeout, an out-of-memory. The retry starts the whole thing again.

For a pure calculation that is wasted time. For a step that sent an email, opened a pull request or charged a card, the retry does it a second time. "Run it again" is not a safe default once a step touches the outside world.

What you are building

Live surfaces, not screenshots — every one composed from the same components you would install.

Durable runs

A paused run is a database row, not a held process, so it survives a deploy.

Runslast 24h
RunWorkflowStateWaiting onAge
run_8f21Expense approvalAwaiting approvalM. Iyer2h
run_8f19Expense approvalCompleted5h
run_8f04OnboardingResumed after restart1d
run_8ef7Nightly digestFailed · retrying1d

A paused run is a database row, not a held process — which is why it survives a deploy.

The code

A paused run is a row, not a processphp
// This is the whole trick. Nothing is held in memory between steps, so a deploy,
// a crash or a queue restart cannot lose a run that is waiting on a person.
Schema::create('flow_runs', function (Blueprint $table) {
    $table->id();
    $table->string('workflow');
    $table->string('status');        // running | awaiting_input | done | failed
    $table->json('state');           // everything needed to resume
    $table->timestamps();
});
Same graph, both runtimesbash
composer require particle-academy/fancy-flow-php

How to solve it

  1. Install the PHP runtime

    The durable runner executes a workflow as queued jobs rather than one long-running process.

    Run thisbash
    composer require particle-academy/fancy-flow-php
  2. Checkpoint per node, not per run

    One job computes which nodes are ready and dispatches them; another claims a single node and checkpoints it when it completes. A resume picks up from the last completed node instead of the start.

  3. Declare which steps must not be replayed

    A node marked unsafe to replay gets one attempt regardless of the retry setting, because retrying it would repeat the side effect rather than recover from it.

  4. Let a claim be a race, safely

    Node claims are enforced by a unique constraint rather than a check-then-act, so two workers racing for the same node produce a no-op, not a double run.