Build a workflow engine (Temporal / Airflow / Cadence style) (13 scenes)
Scene 12 · Design canvas: choose the right engine
Match each workload to its model — code-as-workflow replay, a DAG scheduler, or a state machine — and defend every choice with the scene that taught the requirement.
Previously
You've earned every mechanism. The capstone isn't a new one — it's choosing the right tool. The same ORDER #1001 can be expressed as Temporal-style code, an Airflow DAG, or a Step Functions state machine. Each fits a different shape of workload, and seeing the 30-day wait and the cancel signal go awkward in a DAG is the cleanest proof of what durable execution is actually for.
Scene 12
Design canvas: choose the right engine
Diagram
Each workload card is matched to an orchestration MODEL. Code-as-workflow replay (durable execution — the model this course taught: you write normal-looking code and durability comes from event history plus deterministic replay) suits long-running, stateful, crash-surviving orchestration. A DAG scheduler (a batch/ETL orchestrator: a directed graph of short, stateless tasks with task-level retry and NO deterministic replay or long in-process wait) suits nightly pipelines. A state-machine workflow (a declarative, serverless model — the workflow is JSON, not code — so there's no determinism worry, at the cost of expressiveness and cloud lock-in) suits cloud-native approval flows. The verifier cites the scene behind every requirement: durable timers (scene 7) and signals (scene 8) are why the 30-day-wait + cancel order needs durable execution and is awkward as a DAG; the absence of any long wait or external input is why the nightly ETL refresh belongs on a DAG. Every knob label echoes a term you already earned.
DAG scheduler = a graph of short stateless tasks, no long wait — the nightly ETL's home
No new machinery this time — just the payoff. Watch a workload land on the canvas: a nightly data-warehouse refresh (Workload B). It's a directed graph of short, stateless tasks — extract, transform, load — with no long wait and nothing to react to mid-run. That shape has a name you already half-know: a **DAG scheduler** (think Airflow) — a batch/ETL orchestrator that runs a graph of short tasks with task-level retry, and notably has NO deterministic replay and no long in-process wait. The verifier flashes green: nothing here needs the durability you spent eleven scenes building, so the DAG is its home. Now the same ORDER #1001 you've followed all arc — charge, reserve, ship, email — rendered three ways at a glance. As **code-as-workflow replay** (Temporal-style: normal-looking code made durable by event history + deterministic replay) the 30-day wait and the cancel signal are first-class. As a **state-machine workflow** (Step Functions: the flow is declarative JSON, serverless, no code to replay) it's tidy but cloud-bound. Drop it on the DAG, though, and watch the 30-day wait and the cancel go visibly awkward — a sensor idling a worker for a month, a cancel with no running actor to message. That awkwardness IS the proof of what durable execution is for.
Implementation
chooseModel
maps a workload's shape to its orchestration model
1def chooseModel(w):2 if w.needs_long_wait or w.needs_signals:3 # durable timer + signal must survive crashes4 return CODE_AS_WORKFLOW_REPLAY5 if w.is_batch_dag:6 # short stateless tasks, task-level retry7 return DAG_SCHEDULER8 return STATE_MACHINE # declarative, serverless
OrderWorkflow.run (code-as-workflow replay)
the 30-day wait + cancel are first-class durable events
1def run(order):2 charge_card(order) # activity, runs once3 reserve(order) # activity, runs once4 # durable timer: dormant, survives crashes5 fired = workflow.await(6 timer = sleep(days=30),7 signal = 'cancel',8 )9 if fired == 'cancel':10 return compensate(order) # refund, release11 ship(order); email(order)
nightly_etl_dag (DAG scheduler)
short stateless tasks, no long wait, no signal
1dag = DAG('nightly_etl', schedule='@daily')2extract = task(extract, retries=3)3transform = task(transform, retries=3)4load = task(load, retries=3)5extract >> transform >> load # dependency edges6# no durable timer, no in-process wait, no signal,7# no deterministic replay — just retry a failed task
Not sure what to ask? Tap a question — the staff engineer answers in the chat panel.