Skip to content

Foundations

Welcome to the Foundations section. This structured learning path takes you from Result types to production-ready workflows.

Work through these topics in order. Each builds on concepts from the previous one.

Result Types

The foundation of typed error handling. Learn ok(), err(), and transformers.

Start here →

Workflows and Steps

Compose operations with run() and createWorkflow(). Master the step() function.

Learn workflows →

Control Flow

Sequential, parallel, and race patterns. Run operations concurrently.

Control flow →

Errors and Retries

Error inference, TaggedError, and resilience with retries and timeouts.

Handle errors →

State and Resumption

Persist workflow state. Resume after crashes. Enable caching.

Manage state →

Streaming

Real-time data streaming. AI token streaming. Transform streams.

Stream data →

By the end of this section, you’ll understand:

  • Type-safe error handling - No more catch (error: unknown)
  • Workflow composition - Chain operations that can fail
  • Automatic error inference - TypeScript computes your error union
  • Resilience patterns - Retries, timeouts, and backoff strategies
  • State persistence - Save and resume workflows across restarts
  • Real-time streaming - Stream tokens, progress, and live updates

Where workflows, runs, and options live:

flowchart LR
  subgraph creation [Creation-time options]
    createWorkflow["createWorkflow(name, deps, options)"]
    options[resumeState, onEvent, cache, ...]
    createWorkflow --> options
  end

  subgraph run [Per-run options]
    workflowRun["workflow.run(fn, exec)"]
    exec[onEvent, signal, resumeState, ...]
    workflowRun --> exec
  end

  subgraph never [Never here]
    bad["workflow.run(fn, opts)"]
    bad --> ignored[ignored, Awaitly warns]
  end

  subgraph durable [Durable]
    durableRun["durable.run(deps, fn, { id, store })"]
    durableRun --> auto[auto checkpoint per step]
  end

  creation --> run
  run --> durable
  • Creation-time: Pass options to createWorkflow(name, deps, options). They apply to every run.
  • Per-run: Pass options to workflow.run(fn, exec) (or workflow.run(args, fn, exec)). They apply only to that invocation.
  • Never: Pass options only via workflow.run(fn, config) or createWorkflow(..., options).
  • Durable: durable.run(...) wraps a workflow with a store and checkpoints after each keyed step.
ConceptWhat it does
ok(value)Create a success Result
err(error)Create a failure Result
step('id', fn)Execute operation, exit early on error
createWorkflow('workflow', deps)Create reusable workflow with error inference (deps optional: createWorkflow('name') for no deps)
allAsync([...])Run operations in parallel (fail-fast)
step.retry(id, fn, opts)Retry with backoff on failure
resumeStateContinue from saved checkpoint

Start with Result Types to learn the core building block of awaitly.