Workflows
A workflow is a durable state machine that orchestrates several functions as one reliable unit of work.
A single function is the right tool for one step. Real processes are usually several steps with logic between them: validate an order, screen it for fraud, charge the card, then fulfill or reject it. Some steps run in parallel. Some are conditional. Some fail transiently and need a retry. You can wire that together by having functions call each other. But then the orchestration lives in your code. Nothing records how far an execution got. A crash midway leaves you guessing. A workflow makes the orchestration a first-class, durable object instead.
Definition and execution
Workflows use two custom resources, mirroring the split between a program and a running process:
- A
Workflowis the definition — a named state machine that says which functions run, in what order, with what branching, retries, and error handling. - A
WorkflowRunis one execution of that definition against a specific input. You create a run each time you want the workflow to happen. Each run has its own state and history.
The definition is authored once and reused. Every invocation is a new run.
What makes it durable
Every step a run takes — scheduled, succeeded, failed, retried, a timer fired, branches joined — is appended to an event log in the statestore using compare-and-swap. The log is the single source of truth for where a run is. The engine’s own state is derived: it rebuilds a run’s position by folding its event log, then decides the next step.
That design buys four things:
- Restart survival. If the controller restarts mid-run, it reads the log back and continues — nothing is re-run that already succeeded, and nothing is lost.
- Resume exactly where it stopped. A run picks up from its last recorded step, not from the beginning.
- Retries with backoff. A transient function failure (a 5xx) is retried automatically. A permanent one (a 4xx typed error) is not.
- Typed-error routing.
A step can catch a named business error (
PaymentDeclined) and route to a different state, separately from infrastructure retries.
flowchart TB trigger["CLI / Trigger"]:::user -->|"create WorkflowRun"| engine["Workflow Engine"]:::fission engine -->|"invoke step (internal path)"| router["Router"]:::fission router --> pod["Function Pod"]:::pod engine -->|"append every step (CAS)"| log["Statestore Event Log"]:::store engine -->|"durable delay"| timers["wf-timers Queue"]:::store log -.->|"fold to resume"| engine classDef user fill:#ffffff,stroke:#94a3b8,color:#1f2a43 classDef fission fill:#e8f0fe,stroke:#2d70de,color:#1f2a43 classDef pod fill:#e6f7f1,stroke:#11a37f,color:#1f2a43,stroke-dasharray:5 3 classDef store fill:#fff7e0,stroke:#dba514,color:#1f2a43,stroke-dasharray:5 3
The state types
A workflow is built from a small set of state types:
- Task — invoke a function.
- Choice — branch on the data, with no function call.
- Parallel — run several branches concurrently and join their results.
- Map — run one branch per element of an array, with a concurrency limit.
- Wait — pause the run durably for a set duration.
- Succeed / Fail — terminate the run.
See Authoring workflows for the full field reference.
When to use a workflow
Reach for a workflow when an operation is multiple steps that must complete reliably as a whole. Good signals include parallelism, conditional routing, retries, durable waits, or a need to know afterward exactly what happened.
Prefer the simpler tools when they fit:
- A single function, possibly async, is enough for one unit of work — see Asynchronous invocation.
- Independent event-driven reactions are better modeled as separate triggers.
Related
- Workflows usage guide — enable, author, run, and inspect workflows.
- Statestore — the durable event log a run is recorded in.
- Functions — the steps a workflow orchestrates.