Workflow execution engineJava 21 · Spring Boot 4 · PostgreSQL · Apache-2.0

Timed to
the millisecond.
Durable by design.

A domain-agnostic engine that turns a directed graph of steps into a recorded, resumable run. Hand it a trigger — it plans, claims, executes, transitions, recovers.

// the instrument reads a live run
The database is the queue. There is no broker, and no in-memory timer to lose on restart. Every step is a row; every transition is recorded. Work advances only when due_at says so.
READ THE SOURCETRACE A RUN
RUN  PRIORITY_ALERT  ›  subject-42  ›  idem WEM1|9f2c…WORKER POLLING · 5s
90°180°270°360°01 · PLAN02 · CLAIM03 · EXECUTE04 · TRANSITION05 · RECOVERdelay · due+5mbranch · equalsAnyhttp_request · POSTdep_count−−retry · backoff
SIG · workflow_run_stepsSWEEP = due_at clock · one revolution per run
§01

The firing order

Five mechanisms turn in the same sequence on every run — deterministic, ordered, recorded end to end. Each fires when its phase comes due.

000°PlanFreeze a graph snapshot, write one step row per node, mark the entry step due. The run carries its own copy of the graph forever after.
072°ClaimFOR UPDATE … SKIP LOCKED lets any number of workers drain the queue with no collisions. Postgres is the lock manager.
144°ExecuteBuild the run context, resolve {{ }} templates against it, run the step's code, and persist its outputs for the steps downstream.
216°TransitionDecrement the dependency counts of successor nodes to open what runs next — joins wait for all predecessors — or follow a terminal marker and finalize.
288°RecoverRetry transient failures with bounded backoff; resurrect steps orphaned by a crashed worker. A poison step cannot loop forever.
§02

Tolerances it holds

Three tables, zero foreign keys to your data. Durability, idempotency and per-subject supersession are machined in — not bolted on after.

ADurable runs

Survives the crash

One row per execution. A worker can die mid-step; stale recovery resurrects the orphaned row, retries, and converges. The run is never lost.

BIdempotency

The same event, once

A unique key over workflow · source · subject · event dedupes triggers. Deliver an event twice; the database guarantees exactly one run.

CSupersession

Converge on the newest

A newer run for the same subject supersedes the older in-flight one when their change-sets overlap. No racing duplicates, no stale outcome.

DVersioned graphs

Edit without disturbing flight

JSONB definitions on a draft / active / archived lifecycle. Each run executes its frozen snapshot — editing never touches runs already moving.

§03

Specimen run

A workflow is a DAG of typed steps in JSON. The engine ships no domain knowledge — you register it behind five extension points, as Spring beans, never as edits to the core.

PRIORITY_ALERT.jsonschemaVersion 1
// wait → branch → notify → terminal
{
  "entryNode": "wait",
  "nodes": [
    { "id":"wait", "type":"delay",
      "config":{ "delayMinutes": 5 },
      "transitions":{ "DONE":["check"] } },

    { "id":"check", "type":"branch_on_field",
      "config":{ "field":"event.priority",
                "op":"equalsAny", "values":["high"] },
      "transitions":{
        "HIGH":["notify"],
        "NORMAL":{ "terminal":"COMPLETED" } } },

    { "id":"notify", "type":"http_request",
      "config":{ "method":"POST",
                "url":"https://hooks.example/alert" },
      "transitions":{ "SUCCESS":{ "terminal":"COMPLETED" } } }
  ]
}
EXTENSION POINTS · SPI
WorkflowStepTypea step to execute
RunContextContributornamed context slots
GraphValidationRuleauthoring checks
TriggerValidatorvalidate triggers
WorkflowHttpClientoutbound HTTP
// bundled examples — delay · set_variable · branch_on_field · http_request · slack_notify. Illustrations of the contract, not the kernel.
Domain-agnostic · broker-free · 0.1.0-SNAPSHOT

Hand it a
trigger.

implementation dev.sarathkumarks:camshaft-engine
VIEW ON GITHUBREAD HOW IT WORKS