Versioning: the year-later replay — getVersion gates for in-flight executions

Editing a live workflow's code makes an in-flight execution replay against a different step sequence than its recorded history, diverging into a non-determinism error — so the safe path is a version gate that routes old executions down the old path and new ones down the new path, both deterministic.

Previously

A version gate lets ORDER #1001, started a year ago under v1, wake and replay safely alongside v2 executions. You now hold the full toolkit: history, replay, activities, workers, retries, idempotency, timers, signals, sagas, children, versioning. The last question isn't a new mechanism — it's judgment: for a real workload, is this code-as-workflow replay model even the right tool, or is a DAG scheduler or a state machine the better fit?

Scene 11

Versioning: the year-later replay

  1. Watch
  2. Try it
  3. Predict
  4. Capture
DEPLOY v2 — one codebase, two live executionsVERSION GATEversion gate OFF — old run replays new …deployed code · v2ChargeCard($42)FraudCheck()⚑ReserveInventory()Ship()Email()blue = workflow (replayed)red = activity (runs once, recorded)ORDER #1001started v1 · still in flightStart v1replayedChargeCard ✓ $42replayedTimer 30dexecuting for realreplay head — grays replayed steps, stops at the first un-recorded onereplays cleanly on its routed branchORDER #1002started v2 · todayStart v2replayedChargeCard ✓ $42replayedFraudCheck ✓executing for realreplay head — grays replayed steps, stops at the first un-recorded onereplays cleanly on its routed branchORDER #1001 was started a year ago under v1; #1002 today under v2. Both replay through this one deployed codebase.
↓ one deployed codebase (v2) — both runs replay through it
What to watch for

It's a year later. ORDER #1001 charged the card $42, then went to sleep on its 30-day timer — and it's STILL alive, waiting to wake. Today you ship v2 of the order workflow: it inserts a FraudCheck between ChargeCard and ReserveInventory. Here's the trap you can't see in a normal service. There is only ONE deployed codebase now — v2 — and BOTH executions replay through it. But #1001's recorded history was written under v1: it never has a FraudCheck event, because that step didn't exist when it ran. A run like #1001 — started under older code and still alive, carrying expectations frozen into its history — is an in-flight execution. #1002, started today, ran against v2 from its first step, so its history already carries FraudCheck. Watch both executions appear on the strip: same code ahead of them, but two different histories behind them.

Continue unlocks when the animation finishes.
Implementation

Highlighted lines are the ones running in the diagram right now.

Worker.replay
re-run the code, match each command against history
def replay(execution):
history = execution.history # frozen, append-only
cursor = Cursor(history)
for cmd in run_workflow(execution):
recorded = cursor.next_event()
if recorded is None:
return execute_live(cmd) # caught up
if cmd.kind != recorded.kind:
raise NonDeterminismError(cmd, recorded)
feed_back(cmd, recorded.result) # don't re-run
Workflow.orderV2
the one deployed codebase both runs replay
def order_workflow(order):
charge_card(order, 42)
v = get_version('fraud', min=1, max=2)
if v >= 2:
fraud_check(order)
reserve_inventory(order)
ship(order); send_email(order)
Engine.getVersion
read the version from THIS run's own history
def get_version(change_id, min, max):
marker = history.find(change_id)
if marker is not None:
return marker.version # what this run committed to
# first time: record max so future replays agree
record(VersionMarker(change_id, max))
return max

Where this sits in Build a workflow engine (Temporal / Airflow / Cadence style)

Scene 11 of 13, in the Evolve & ship act — Version safely, then choose the right engine.. A year-old in-flight execution can't be hot-fixed; a version gate routes old executions down the old path and new ones down the new path, so both replay deterministically.

Up next. 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.

All 13 scenes in Build a workflow engine (Temporal / Airflow / Cadence style) · Every curriculum

Built with Arqly
Every scene in Build a workflow engine (Temporal / Airflow / Cadence style) builds on the one before it.All 13 Build a workflow engine (Temporal / Airflow / Cadence style) scenes