foliot docs

Decisions / 0001 · Declarative step graphs

ADR 0001: Declarative step graphs, not code-as-workflow with replay

Status: accepted · 2026-09-02

Context

Temporal, Cadence and SWF’s Flow framework let you write a workflow as an ordinary function and make it durable by recording every result and replaying the function after a restart. It is expressive, and it is the source of most of the operational pain: workflow code must be deterministic, every edit to in-flight workflows needs version markers, and debugging means understanding why a function ran to line 40 without doing anything.

Herd’s model, as far as it is public, is a work item with a current step and a scheduled time, advanced by an engine that never runs tenant code.

Decision

A workflow is data: an ordered list of steps (task, sleep, wait, choice) with transitions. Handlers are plain HTTP endpoints or pull workers. Branching is declared (choice with a data-only predicate) or chosen by a handler returning next from the declared steps. The engine never evaluates user code.

Consequences

  • No non-determinism bugs; any language can implement handlers with no SDK.
  • Definitions are immutable per version and a run finishes on the version it started on.
  • Less expressive: unbounded loops and dynamic fan-out need explicit steps or later features (child runs, map).
  • If a tenant needs dozens of dynamic branches, that is the signal to reconsider.