Small follow-up on the execution layer side.
I’ve been spiking bedrock_job_queue as an alternative executor backend for Squid Mesh. The initial motivation was to see whether Bedrock could cover the parts a workflow runtime eventually cares about beyond “enqueue a job”: delayed delivery, retries, dead-lettering, worker claims, lease extension/heartbeat, and stale worker recovery.
So far the fit looks promising.
The most interesting part is that Bedrock’s lease model maps very naturally to workflow execution. In a workflow engine, a runnable step is not just a background job. The runtime eventually needs to reason about whether work was claimed, whether the worker is still alive, whether the lease expired, whether the step completed, and whether failure should retry or become terminal.
The spike currently covers:
- enqueueing Squid Mesh payloads into Bedrock Job Queue
- delayed jobs
- cron-style activation
- priority ordering
- tenant/queue isolation
- retries and dead-letter behavior
- worker leasing
- heartbeat / lease extension
- complete / fail paths for leased work
There were some integration rough edges, mostly around using newer Bedrock Job Queue changes and understanding the low-level keyspace/lease APIs, but nothing that felt like the wrong abstraction.
The bigger takeaway for me is that Bedrock seems like a strong match for clustered workflow runtimes because the storage layer is already oriented around distributed coordination. Squid Mesh still has its current persistence/runtime path, but this spike is pushing the architecture toward clearer boundaries:
- Squid Mesh owns workflow semantics
- the journal/runtime layer owns durable workflow facts
- executor adapters own concrete queue and lease mechanics
That separation feels important if Squid Mesh is going to support different execution backends
without baking one job system into the workflow model.
i.e.
+-----------------------------------------------------+
| Squid Mesh |
+-----------------------------------------------------+
| Public API: start_run / inspect_run / explain_run |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Squid Mesh Runtime |
+-----------------------------------------------------+
| Plans work, applies results, retries, pauses, |
| cancels, completes, inspects, and explains |
+-----------------------------------------------------+
|
v
+-----------------------------------------------------+
| Jido Journals |
+-----------------------------------------------------+
| Durable workflow facts: runs, attempts, claims, |
| heartbeats, completions, failures, terminal state |
+-----------------------------------------------------+
| ^
v |
+----------------------------+ +----------------------------+
| SquidMesh.Executor | | SquidMesh.Executor.Leases |
+----------------------------+ +----------------------------+
| enqueue jobs / cron / delay| | claim / heartbeat / finish |
+----------------------------+ +----------------------------+
| |
+-------------+------------+
|
v
+----------------------------------------------------+
| Backend Adapter |
+----------------------------------------------------+
| Queue: enqueue, delay, cron delivery |
| Lease: claim, heartbeat, expiry, complete/fail |
+----------------------------------------------------+
|
v
+----------------------------------------------------+
| Backend Storage |
+----------------------------------------------------+
| Jobs, leases, worker liveness, delivery metadata |
+----------------------------------------------------+
I don’t think this means relational DBs are a bad fit for workflow engines in general. Postgres + Oban is still a very strong default (we’d just need to implement the leasing behavior).
The distinction I’m seeing is between workflow facts and workflow execution coordination. Workflow facts/history/inspection fit relational storage well. But the executor side starts looking less relational once you care about claims, leases, heartbeat extension, stale worker recovery, delayed visibility, and multi-node ownership.
That is where Bedrock feels like a better-shaped tool: the queue/lease layer is naturally a distributed coordination problem, not just a table of jobs.