SuperAPI AI Directory

workflow-engine-design

Design & creation

View repository

Updated 10-16 09:50

About this skill

Workflow Engine Design

Build the engine layer — not individual idempotent operations (see idempotent-financial-workflows), but the runtime that sequences them durably.

Orchestration vs Choreography

  • Orchestration: central coordinator holds explicit state; easier to observe, debug, and audit. Use for multi-step money flows and compliance-sensitive sequences.
  • Choreography: services react to events on a shared bus; decoupled, harder to trace. Use for loose fan-out notifications.
  • Hybrid: orchestrator per bounded context, events between contexts.

State Machine Design

  • Name every state and every valid transition before writing code.
  • Store state durably before executing side effects — never derive current state from side-effect logs.
  • Terminal states: completed, failed, cancelled, compensated.
  • Persist the full input/output of each step; a replay must reproduce the same decisions without re-running external calls.

Durable Execution Primitives

  • Step isolation: each step reads input, executes idempotently, writes output + new state atomically.
  • Outbox: cross-service steps commit local state + outbox message in one transaction; a relay delivers externally.
  • Timers/delays: store as a scheduled-event record; a polling worker or dedicated scheduler fires it. Never sleep().
  • Suspension/resume: workflow pauses waiting for an external callback; store a resume token; callback delivers it and the engine re-schedules the workflow.

Compensating Transactions (Sagas)

  • For each step with an external side effect, register a compensating action before execution.
  • On failure, execute compensations in reverse order — each compensation must also be idempotent.
  • Record compensation outcome; never silently swallow compensation errors.

Worker Concurrency Model

  • Lease-based polling: worker claims a task with a TTL lease; heartbeats extend it; expiry allows re-claim.
  • Fan-out/fan-in: parallel branches share the workflow ID with a branch index; fan-in waits for all branch completions.
  • Backpressure: bounded worker pool; queue-depth metric drives horizontal scaling.

Workflow Versioning

  • Assign a schema version to each workflow definition. Running instances finish on the version they started.
  • Safe changes: add optional steps, add new terminal paths.
  • Breaking changes (require a new version): remove, reorder, or rename steps.
  • Migration: drain old version to completion, then decommission the handler.

Dead-Letter and Stuck Workflows

  • Max attempt limit per step → move to dead_lettered state with full context snapshot.
  • Ops tooling required: list stuck/dead-lettered workflows; replay from a specific step; force-complete a terminal step.

Testing Long-Running Workflows

  • Unit: synchronous in-process runner — no queues, no real timers. Inject step fakes for each external outcome (success, transient failure, permanent failure, duplicate callback).
  • Time advance: trigger timer steps programmatically; never sleep() in tests.
  • Regression: replay a recorded production workflow trace and assert final state.