Skip to content

Architecture

Use a restricted workflow DSL in Dart. A workflow function may use normal control flow, but every durable boundary goes through WorkflowContext:

  • serviceTask / activity for I/O and side effects;
  • userTask for assigned work;
  • waitForSignal for external events;
  • sleep for durable time;
  • a stable operation id on every await.

Direct I/O, wall-clock reads, randomness, mutable globals, and unregistered futures are forbidden in orchestration code.

WorkflowRuntime is the canonical runtime. LegacyWorkflowEngine is the graph compatibility surface for in-flight product runs.

Component Split

ComponentOwnsMust not own
Workflow definitionDeterministic orchestration and await IDsI/O, clocks, randomness
Decider / runtimeReplay, commands, retries, statusBusiness side effects or SQL
Activity workerVersioned handlers, heartbeats, idempotencyWorkflow control-flow state
User-task APIAssignment, completion, validation, expiryA long-lived process
Storage interfaceAtomic run/history/command transitionsSupabase-specific SQL
Postgres adapterTransactions, row locks, SKIP LOCKED, fencingWorkflow-domain branching
Timer / recoveryTimers, expiry, expired leases, interrupted decisionsArbitrary business code
DesignerConstrained document and visualizationRuntime state

API, decider, worker, and recovery roles can be separate processes or one WorkflowServerApplication. Correctness comes from storage contracts, not from which replica handled the last request.

Progress Model

  • history.sequence is the ordered audit trail.
  • runs.revision fences concurrent decisions.
  • commands are pending, claimed, completed, failed, or cancelled.
  • operationKey identifies a logical await across replay.
  • claimGeneration fences stale workers after lease reassignment.

blocked is healthy. It means the run is waiting for durable external work.

Definition Digest

A run stores code, version, and digest. Workers reject a digest mismatch instead of replaying history against changed logic. Changing behavior requires a new version.

Visualization

Arbitrary Dart cannot be converted into a complete graph. Attach an optional WorkflowDocument when you need a pre-run inspector map. Without it, the inspector builds an observed operation map from history as the run executes.

See Also