Skip to main content
workflow

Workflow Engine (Temporal, Cadence, AWS Step Functions)

Orchestrates long-running, stateful multi-step processes — the right tool when a business flow involves many services and can span days.

Why it exists

Some processes are hard: 'Charge the card, then update the shipping order, then send a confirmation email — and if any step fails, roll back the previous ones.' Doing this in application code means writing retry logic, compensation logic, state persistence, timeout handling, and observability yourself — every time. Workflow engines factor all of this out. You write the business logic; the engine handles durability, retries, and compensation.

How it works

A workflow is defined as code (Temporal, Cadence) or as a JSON state machine (Step Functions). Each step is an activity — a call to a service or a piece of business logic. The engine persists the workflow's state after every step. On worker failure, the engine reruns the workflow from the last checkpoint. Because activities may re-execute, they must be idempotent. Workflows can wait for external signals (user confirmation), sleep for days, and roll back via explicit compensation actions.

Scaling characteristics

Temporal / Cadence handle millions of concurrent workflows in production; state size per workflow is bounded (~100 KB) but total state can be terabytes. Latency per step is a few ms of engine overhead + the activity itself. Throughput scales with worker fleet + engine cluster; typical clusters run 100K workflow starts/sec.

When to use it

  • Multi-service transactions (order → payment → inventory → shipping)
  • Long-running processes (KYC, onboarding, subscription lifecycle)
  • Human-in-the-loop flows (approval workflows)
  • Compensating transactions across services (Saga pattern implementation)
  • Retryable ML pipelines (data prep → training → deployment)
  • Batch processing with complex step dependencies

When NOT to use it

  • Simple synchronous requests — the overhead isn't worth it
  • High-throughput low-latency work — the engine adds latency; a direct queue is faster
  • Two-step processes where a queue + retry is enough
  • You're already using Airflow and it works — don't switch just for the sake of it

Failure modes

  • Non-idempotent activities cause corruption on retry — always design activities to be idempotent
  • Workflow history grows unbounded on long-running workflows — use continueAsNew to reset
  • Poison workflow: a bug in the code causes infinite retry — set retry limits + alerts
  • Engine cluster overloaded from too many workflows — capacity plan carefully
  • Debugging is harder than synchronous code — invest in observability early

Alternatives

  • Choreographed sagas via events — no central engine; more moving parts to reason about
  • A queue with retry — good for 2-step workflows; falls apart at 5+ steps
  • Airflow — better for scheduled DAGs (batch); worse for event-triggered long-running flows
  • Custom code + database state — reinventing the wheel; usually a mistake at any scale

Interview questions

  • Explain the Saga pattern. When would you use a workflow engine to implement it vs. choreographed events?
  • How do you handle a workflow that fails halfway through — resume from where it stopped or start over?
  • Design a subscription-renewal workflow that runs monthly, retries on payment failure, and grace-periods before cancellation.
  • What does 'idempotent activity' mean in Temporal, and why is it critical?
  • Your workflow started before you deployed a code change. What happens when it resumes?
  • How would you monitor the health of 10M concurrent workflows?
The story of long-running work

2014, Uber: some workflows run for weeks — where do you write that code?

A request-response cycle is a few hundred milliseconds. A background task is a few seconds. But what about workflows that legitimately need to run for hours, days, or weeks? An Uber Freight ship takes 3 days between waypoints. A Stripe payout batch runs monthly. A user onboarding sends emails over 30 days. If your program crashes at hour 27 of a 3-day workflow, you can't just retry from scratch — that's data corruption. You need durable execution.

For decades this problem was solved badly: cron jobs + state in a database + custom retry logic + custom timers, all glued together with prayer. Every team reinvented the same primitives and got them subtly wrong. Then in 2014, Uber's Cadence project (later open-sourced) codified the solution: durable execution. You write workflow code as if crashes couldn't happen. The engine transparently records every side effect and, on failure, replays the code to the exact point of the last recorded action.

The Cadence team (Maxim Fateev + Samar Abbas) spun out and built Temporal in 2019 — the modern industry standard. AWS Step Functions (2016) took the state-machine approach — you describe workflows as JSON, AWS executes them. Apache Airflow (2015) focused on data pipelines — DAGs of tasks, mostly scheduled. Prefect and Dagster modernized the data-workflow space. Whether you're building financial settlement, ML pipelines, or user onboarding — a workflow engine is the correct abstraction for "long, stateful, retryable" work.

The core insight: code is fragile; state is durable. A workflow engine flips this: you write straightforward code (loops, conditionals, awaits) and the engine makes it survive crashes by persisting every non-deterministic decision. Combined with retries, timeouts, and compensations, this lets you express "book flight then hotel; if hotel fails, refund flight" in 10 lines instead of 1000. The trade: your workflows must be deterministic (idempotent, no wall-clock, no random) so they can be replayed. That constraint is what makes durability possible.

When you need one
Long-running (hours-weeks)
Multi-step processes with waits, human approvals, external events.
Multi-step + failure recovery
Saga patterns. Compensating actions. Partial rollback.
Cross-service coordination
Order fulfillment across 10 microservices with dependencies.
Data pipelines (Airflow)
Scheduled DAGs. Data engineering ETL.
Not a fit for: sub-second work (use a queue). Simple cron jobs (just use cron). One-shot deployments (use scripts).

Historical timeline

  1. 1970s
    BPM & workflow theory
    Business process modeling emerges. Petri nets, workflow reference model. Ideas that would later become software.
  2. 1993
    Workflow Management Coalition
    Industry group standardizes workflow terminology + interchange formats.
  3. 2001
    BPEL (BPEL4WS)
    Business Process Execution Language for Web Services. XML orchestration. Complex + verbose but foundational.
  4. 2004
    jBPM open-sourced
    Java-based workflow engine. First widely-used OSS BPM engine.
  5. 2008
    Cadence patterns paper (Hohpe)
    Enterprise Integration Patterns catalogs saga, compensating transaction, process manager.
  6. 2010
    Microsoft Workflow Foundation
    WF integrates workflow into .NET. Popular in enterprise. Predecessor of Durable Functions.
  7. 2014
    Uber builds Cadence
    Maxim Fateev + Samar Abbas build Cadence at Uber for durable orchestration. Amazon SWF inspired. Later open-sourced (2017).
  8. 2015
    Apache Airflow (Maxime Beauchemin at Airbnb)
    Python-first DAG-based scheduler. Focused on data pipelines. Explodes in data engineering.
  9. 2016
    AWS Step Functions
    Serverless workflow. JSON state machine description. Deep AWS integration.
  10. 2016
    Azure Durable Functions
    Microsoft ports the durable-execution idea into serverless. Uses replay-based determinism.
  11. 2018
    Prefect founded
    Jeremiah Lowin builds Prefect — modern Airflow alternative. Better DX, Python-native, dynamic workflows.
  12. 2019
    Temporal spun out of Cadence
    Fateev + Abbas leave Uber, build Temporal — the polished commercial evolution of Cadence.
  13. 2019
    Dagster launched
    Nick Schrock builds Dagster — asset-first orchestrator. Data-quality focus.
  14. 2022
    Temporal Cloud GA
    Managed Temporal service. Removes ops burden. Adoption accelerates in fintech, ML, gaming.
  15. 2024
    AI-native workflows
    LLM orchestration (LangChain, LlamaIndex) becomes a special case of workflow orchestration. Convergence with agents.

Durable execution: how Temporal survives crashes

The magic of a modern workflow engine is durable execution. Your code writes as if crashes can't happen; the engine records every activity result and replays deterministically on failure. Watch it play out:

Auto-advances every 2.6s

1. Workflow starts

workflow.run() begins. Engine records: 'started' at t=0.

Durable journal
1. started
The constraint: workflow code must be deterministic. No wall-clock (use workflow.now()). No random (use workflow.random()). No file I/O in workflow code (only in activities). Because replay must produce the same sequence of decisions the first execution did.

Sagas: distributed transactions without 2PC

Multi-service workflows need to coordinate transactions. Two-phase commit (2PC) doesn't scale in microservices — you can't hold locks across service calls. The answer is the Saga pattern: break a distributed transaction into a sequence of local transactions, each with a compensating action that undoes it if a later step fails.

Two-phase commit (won't work)

Coordinator: prepare Flight
Flight: prepared (locked)
Coordinator: prepare Hotel
Hotel: prepared (locked)
Coordinator: commit both
// Locks held for whole distributed txn.
// Coordinator crashes = locks stuck forever.

Requires shared coordinator + tight coupling. Locks span services. Cascading failures.

Saga (works!)

workflow:
  try:
    flight = bookFlight()   // committed
    hotel = bookHotel()     // committed
    charge = chargeCard()   // committed
  catch (err):
    // Run compensations in reverse:
    refundCard(charge)      // if reached
    cancelHotel(hotel)      // if reached
    cancelFlight(flight)    // if reached

Each step is a local transaction. Failure triggers compensations. Eventual consistency.

The workflow engine's job: track which steps completed, run compensations in reverse on failure, resume idempotently across crashes. Temporal, Cadence, Step Functions all model this cleanly.

Compensating actions — the semantics of undo

A compensating action isn't a rollback — you can't rollback across service boundaries. It's a business-level reversal: cancel the booking, refund the card, send an apology email. Design them deliberately:

Idempotent

Running the compensation twice = same result as once. Refund transaction ID X even if already refunded.

Reversibility asymmetry

You can't always "undo." Emails already sent. SMS delivered. Design the workflow so those actions happen LAST after all reversible steps.

Retry with backoff

Compensations may fail too. Retry with exponential backoff. Alarm if compensation stuck past N tries.

Booking example done right: reserve inventory (reversible) → charge card (compensable via refund) → send confirmation email (side-effectful, put LAST). If email fails, everything before it is still fine.

Orchestration vs Choreography — two workflow architectures

Two philosophies for multi-service workflows:

Orchestration (Temporal, Step Functions)

A central workflow engine drives each step. Explicit workflow code.

workflow orchestrator:
  bookFlight()
  bookHotel()
  chargeCard()
  sendConfirmation()
Pros: Explicit control flow. Visible in code. Easy to debug + change.
Cons: Orchestrator is a bottleneck. Services must expose activity APIs.

Choreography (event-driven)

Each service reacts to events from previous steps. No central coordinator.

FlightService: on FlightRequested → book → emit FlightBooked
HotelService:  on FlightBooked → book → emit HotelBooked
PaymentService: on HotelBooked → charge → emit Charged
EmailService:  on Charged → send
Pros: Loose coupling. No central bottleneck. Easy to add services.
Cons: Flow is implicit — hard to reason about. Debugging distributed traces required.
Modern advice: orchestration for critical business workflows with strict ordering (payments, onboarding). Choreography for reactive systems and event fan-out. Most large orgs use both, in different contexts. Fowler + Newman both advocate mixing consciously.

Product comparison

ProductTypeModelStrengthWeakness
TemporalDurable executionOSS + CloudBest-in-class DX. Code-as-workflow. Multi-language (Go, Java, TS, Python).Ops complexity for self-hosted. Cost at scale for Cloud.
Cadence (Uber)Durable executionOSSTemporal's ancestor. Battle-tested at Uber. Java + Go.Smaller ecosystem than Temporal. Uber-centric roadmap.
AWS Step FunctionsState machineManagedServerless. Deep AWS integration. Visual designer. Pay-per-transition.JSON state machine can get ugly. AWS-only. Cost at scale.
Apache AirflowDAG schedulerOSSStandard for data pipelines. Huge community. Python-native.Not for long-running (hours) work. Scheduler is a bottleneck. UI slow.
PrefectModern data workflowOSS + CloudBetter DX than Airflow. Dynamic DAGs. Hybrid execution.Smaller than Airflow. Cloud tier costs.
DagsterAsset-first workflowOSS + CloudData quality + lineage first-class. Testable pipelines.Younger. Learning curve for asset model.
Argo WorkflowsK8s-native DAGOSS (CNCF)Runs each step as a K8s pod. Fits K8s-first orgs. GitOps friendly.K8s-only. Kubernetes ops complexity.
Azure Durable FunctionsDurable executionManagedServerless. .NET-native. Replay-based determinism.Azure-only. Cold start latency. C# / Python biased.
GCP Cloud WorkflowsState machineManagedYAML-defined. GCP integration. Pay-per-execution.GCP-only. Less powerful than Step Functions.
RestateDurable execution + RPCOSS + CloudNewer. Combines durable execution with RPC semantics. Simpler mental model.Very new (2023). Ecosystem building.
Netflix ConductorOrchestrationOSSNetflix-scale. JSON workflow definition. Language-agnostic.Older architecture. Ops complexity.
Camunda BPMNBPMN-basedOSS + EnterpriseBusiness-analyst-friendly (BPMN diagrams). Enterprise features.BPMN is verbose. Java-centric. Slower iteration than code-based.

How to choose: Business workflows with long-running steps → Temporal (or Cloud) for modern code-as-workflow. AWS shop + simple state machines → Step Functions. Data pipelines → Airflow (community) or Dagster (modern). Kubernetes-native → Argo Workflows. Business-analyst-driven → Camunda.

12 real-world workflow engine deployments

Uber

Cadence for driver/rider matching + more

Uber uses Cadence for hundreds of workflows: driver onboarding, matching, payments, rating disputes, dynamic pricing. Some run for weeks. Cadence handles retries, timeouts, human intervention.

Coinbase

Temporal for money movement

Coinbase runs Temporal for withdrawals, transfers, reconciliation. Financial correctness demands durable execution. Sagas across banking APIs + on-chain confirmations.

Airbnb

Airflow for the data platform

Airbnb built Airflow. Powers thousands of daily DAGs — data warehousing, ML training, business reports. Standard tool of the data engineering world.

Netflix

Conductor for content processing

Netflix built Conductor for video processing pipelines. Each new title triggers a workflow that transcodes, generates thumbnails, distributes to Open Connect. Handles retries + partial failures gracefully.

Stripe

Homegrown workflow engine

Stripe built a custom workflow engine for payouts, disputes, subscription renewals. Runs at massive scale. Interesting design constraint: idempotency + auditability at every step.

Snap Inc.

Temporal for signup + ads pipelines

Snap uses Temporal for user signup workflows (multi-step verification), ad campaign orchestration. Scales to millions of concurrent workflows.

DoorDash

Cadence for order + delivery lifecycle

Every DoorDash order flows through a Cadence workflow: assign restaurant, dispatch dasher, track pickup, monitor delivery, handle refunds. 30+ minutes end-to-end.

Twilio

Custom workflow for SMS delivery routing

Twilio's SMS routing runs on a custom workflow engine. Each message may go through multiple carriers, retries, geo-checks. Durable — no lost messages.

Datadog

Custom + Temporal hybrid

Datadog runs SLO computation as Temporal workflows. Long-running aggregations that survive restarts. Also uses custom orchestration for high-volume metrics.

OpenAI

LLM training pipelines

OpenAI runs training pipelines on internal orchestration + Airflow-like tools. Fine-tuning jobs, evaluation runs — all as workflows with retries + checkpointing.

Shopify

Temporal for merchant sync + checkout

Shopify uses Temporal for third-party sync workflows (Amazon, eBay integrations), checkout multi-step processes. Handles retries when partner APIs flake.

Instacart

Airflow + custom for ML + logistics

Instacart runs Airflow for data + ML pipelines. Custom logistics orchestration for shopper dispatch. Hybrid data + operational workflow story.

Key takeaways

  • 1A workflow engine is durable execution — code that survives crashes by journaling every side effect.
  • 2You need one when work spans minutes to weeks, has multiple failure-prone steps, or coordinates across services.
  • 3Sagas replace 2PC in microservices: sequence of local transactions with compensating actions on failure.
  • 4Compensations must be idempotent. Retry-safe. Design workflows to put irreversible side effects LAST.
  • 5Orchestration (central engine) for critical flows. Choreography (event-driven) for loose coupling. Mix consciously.
  • 6Determinism constraint: workflow code can't use wall-clock, random, or file I/O directly. That's how replay works.
  • 7For code-as-workflow: Temporal is state-of-the-art. For data pipelines: Airflow. For AWS-native: Step Functions.
  • 8Cron is not a workflow engine. If you find yourself building retry + state in your cron job, you need one.

References & further reading

  • Garcia-Molina, H. & Salem, K. (1987). "Sagas." The foundational sagas paper.
  • Hohpe, G. & Woolf, B. (2003). Enterprise Integration Patterns. Catalog of process manager, saga, compensating transaction.
  • Fowler, M. (2015). "Orchestration vs Choreography." Blog post.
  • Newman, S. (2015). Building Microservices. Excellent chapter on sagas + orchestration.
  • Fateev, M. & Abbas, S. (2020). "Temporal Whitepaper." The definitive intro to durable execution.
  • Amazon (2016). "Introducing AWS Step Functions." Announcement blog + docs.
  • Beauchemin, M. (2016). "The Rise of the Data Engineer." Airflow context.
  • Uber Engineering (2017). "Introducing Cadence." Origin story of the modern durable execution paradigm.
  • Temporal Docs: "Concepts" section. Best conceptual guide to workflows + activities + tasks.
  • Kleppmann, M. (2017). DDIA, chapter 9 (Consistency + Consensus) provides theoretical grounding.