durable-workflow/waterline
Waterline brings durable workflow execution to Laravel. Define multi-step workflows as PHP classes, run them reliably with retries and delays, and inspect progress from a database-backed store. Ideal for long-running background processes that must survive failures.
Waterline is an operator UI, not a workflow-authoring library. You install it next to an existing Durable Workflow runtime and use it to answer the questions that come up during incidents and support tickets: Which run is stuck? Which activity keeps retrying? Is the queue backed up? What exactly happened at 14:32? Treat it as the Laravel equivalent of Temporal’s Web UI — a window into runtime state, plus a small set of repair actions.
Minimal path:
composer require durable-workflow/waterline in the same Laravel app (or a dedicated ops app) that can reach the workflow store. Laravel package auto-discovery should register the provider; if not, add it to config/app.php.php artisan waterline:publish (the release notes’ documented upgrade path); config publishing still goes through vendor:publish — verify the tag in the README rather than guessing.Where to look first: the repository README and contributing guide for build/test/install commands, then the organization-wide agent guide at durable-workflow/.github/AGENTS.md, which the repo’s agents/AGENTS.md defers to for shared product and conformance rules. The repo-specific guide is deliberately thin, so budget an hour reading source if the README is sparse.
First real use case: take a failing workflow you already know about (e.g. an order-fulfilment run that exhausted retries) and use Waterline to walk its history — input, each activity attempt, backoff timing, terminal error — then use the retry/repair action to re-drive it. That single loop (find, inspect, repair, confirm) is 80% of day-to-day value.
Two deployment shapes. Either mount Waterline inside the main Laravel app (fastest; shares the DB connection and auth) or deploy it as a separate internal ops app pointed at the production workflow store. The monolith is fine for a single team; the separate app is better once you want on-call engineers to have access without granting them your application’s full admin surface. If you take the service-image route, pin the image tag to the matching Waterline version (e.g. 2.11.2) — the release notes explicitly call out deploying the versioned image alongside the Composer upgrade.
Gate it like an admin panel. Add the routes behind your existing auth + an is_operator gate or role middleware. Do not rely on the package’s default route group being obscure. A short middleware in config/waterline.php pointing at a dedicated guard is the cleanest pattern:
// app/Providers/AuthServiceProvider.php
Gate::define('viewWaterline', fn (User $u) => $u->hasRole('operator'));
Treat asset publishing as a build step. Every Waterline upgrade ships rebuilt frontend assets (2.11.2 is a pure example: the form values, filtering and backfill handlers were untouched, but the bundle changed). Run php artisan waterline:publish as part of your deploy pipeline, not by hand on the server, and commit or artifact the published assets so the UI you test is the UI that ships.
Make workflow type names stable and greppable. The UI’s run list is only useful if OrderFulfilmentWorkflow maps clearly to a class in your codebase. Adopt a convention (App\Workflows\*), and keep the workflow type string in the UI matching the class name so an engineer can jump from a failing run straight to the definition.
Incident runbook integration. Write down three Waterline queries your team will actually run: “failed in last hour,” “retrying > N attempts,” “queue depth above threshold.” Link them from your runbook next to the Grafana/logs links. This turns Waterline from a tool people forget into the first tab on-call opens.
Correlate with application logs. Store your own correlation/business ID in workflow input or memo fields so you can search Waterline by the same ID that appears in Laravel logs and support tickets. Then add a custom link from the run detail page to your log explorer (extension point — see Tips).
Use repair actions as code-reviewed operations. Retry/repair buttons are state mutations. Treat each production use like a manual artisan command: name the operator, note the run ID in the incident channel, and confirm the fix in history afterwards. For repeatable repairs, prefer scripting against the runtime’s API and using Waterline only for verification, so the action is auditable and repeatable.
Accessibility and ops-team fit. 2.11.2 gave schedule status and saved-view selectors translated accessible names, and associated the backfill date and overlap-policy labels with their controls. If your org has accessibility conformance requirements for internal tooling (or you have engineers who rely on screen readers during incidents), this is the release that makes those screens usable — worth calling out in your adoption notes, and worth re-testing after the asset republish.
Local development loop. Point Waterline at a local/SQLite workflow store in local env and use it while developing workflows — watching retries and backoff in the UI is much faster than reading log lines. Keep the route prefix published locally and run waterline:publish locally too, so you catch asset/route collisions (see Gotchas) early.
Pair with metrics, not instead of them. Waterline is pull-based and human-driven. Keep Prometheus/OpenTelemetry metrics for alerting; use Waterline for the why after an alert fires.
composer update durable-workflow/waterline alone leaves stale assets in public/. Always follow with php artisan waterline:publish and a cache clear. Symptom of forgetting: new backend behaviour with an old UI bundle, or a 404 on a hashed asset after deploy.composer.json. With zero dependents on the package, you are an early adopter — read the changelog before every minor bump. Patch releases like 2.11.2 (accessibility-only, handlers unchanged) are low-risk, but still republish assets./waterline is usually fine, /admin is not) and published assets can clash with existing admin panels. Publish assets in CI, not ad hoc on the server, and keep them in source control.require-dev for local inspection, or isolate it in an ops deployment, so an operator UI outage can never affect workflow execution.AGENTS.md; for anything ambiguous, read the package source and the release notes rather than guessing at config keys. Budget for that on first adoption — it’s the main cost of a small, zero-dependent package. The upside: release notes are precise and short, and patches like 2.11.2 tell you exactly what changed and that handlers were not touched.How can I help you explore Laravel packages today?