THIS EXPLANATION
THE ROOM
CDA·81 Computing, Data & AI 7 MIN · 8 STATIONS

Durable execution

A Socratic walk-through of durable execution — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

How does a process survive the machine it was running on disappearing mid-step?

A program is halfway through a long piece of work. It has charged a card, it has not yet booked the seat, and the machine it is running on vanishes — a spot instance reclaimed, a kernel panic, a datacentre rack losing power. When something starts up to take over, what exactly does it have to work with?

The tempting answer is "it restarts the program". But that is precisely the thing we must not do naively, because restarting means charging the card again. So the real question hiding underneath is narrower and stranger: what is the surviving part of a running process, once the machine holding it is gone?

b

Reasoning it through

REASONING #

Let us ask what was lost. A running process holds two quite different sorts of thing. There is the code — the instructions, identical on any machine, trivially reconstructible. And there is the state — the program counter saying which line we reached, the local variables, the contents of the stack. The code was never at risk. Only the state was, because only the state lived in memory on that one machine.

So what if the state were somewhere else? Notice that we do not need to preserve memory itself. We need to be able to reconstruct it. And here is the observation the whole idea rests on: if the program is deterministic, then its state at any moment is completely determined by two things — where it started, and every result it received from the outside world along the way. Same starting point, same sequence of answers, same state. Nothing else is needed.

That reframes the problem entirely, does it not? Instead of continuously copying memory to safety, we only have to record, durably, each result as it comes back: the card charge returned this confirmation id, the timer fired at this moment. Those results are few, small, and unlike memory they are meaningful.

Now play the recovery forward. A new worker picks up the abandoned workflow. It starts the code from the top — genuinely from line one — and runs it. It reaches the card charge and is about to call the payment provider. But the engine consults the record and sees that this step already completed, with this result. So it does not make the call. It hands back the recorded answer and lets the code continue, having spent no money. It does this for every step in the record, in order, until it reaches a step with no recorded result. That is the frontier — the point the old machine actually got to — and from there the code runs for real again.

The word for that reconstruction is replay, and the record is usually called the event history. What is striking is what the workflow code itself experiences: nothing. From inside the function, one line follows another. It has no idea it just executed its first eleven steps at a million times normal speed against a log, and is only now touching the world.

Two things must hold, and they are exacting rather than incidental. The history has to be written durably before the workflow is told the result — otherwise a crash in the gap loses the fact that the card was charged, and replay charges it again. And the code has to be deterministic on replay: if it asks the current time, or generates a random number, then the second run diverges from the first and the recorded results no longer line up with the operations requesting them. Engines enforce this rather than hoping for it — they intercept clocks and random sources, feed recorded values instead, and refuse to continue on divergence.

And one honest limit. Nothing here makes an external side effect exactly-once. If the worker crashed after the payment provider took the money but before the result was durably recorded, the history has no memory of it, and replay will call again. What durable execution actually guarantees is that the workflow's own progress is never lost and never silently duplicated; making the outside world agree still requires idempotency keys at the boundary. That is a division of labour worth being clear about rather than blurring.

c

The analogy

THE ANALOGY #
THE FIGURE

Think of a ship's log rather than a photograph of the bridge. Preserving a voyage by photographing the whole bridge every few minutes — every dial, every crewman's position — is expensive and mostly redundant. The log instead records only the consequential facts: the bearing taken at 04:10, the port cleared at 06:30. Hand that log to a fresh navigator and they can reconstruct where the ship is and carry on from the last entry, without re-sailing a mile.

WHERE IT BREAKS DOWN

a navigator reads the log and understands it, whereas replay does not understand anything — it re-executes the same code blindly, so if the code behaves differently the second time through, the log's entries silently attach themselves to the wrong operations rather than being noticed as inconsistent.

d

Clarifying the model

THE MODEL #

Three refinements are worth making.

First, "durable" is doing precise work in the name. It does not mean the process kept running; the process certainly died. It means the execution — the notion of where this particular piece of work has got to — outlived every machine that ever hosted it. Durability lives in the history store, which is a replicated database, not in any worker.

Second, replay is not a retry. A retry re-attempts one failed operation; replay re-runs the entire function from its first line and suppresses everything already done. This is why log output appears repeatedly during recovery, and why engines mark replayed logging as such.

Third, the common misconception: that this is checkpointing. Checkpointing snapshots state; durable execution records results and recomputes state from them. A memory snapshot is opaque, large, and tied to a binary layout; a history of results is small, inspectable, and survives a code deploy far more gracefully — though not arbitrarily, since changing the sequence of steps in an already-running workflow is exactly the case that breaks replay, and is what versioning APIs exist to handle.

e

A picture of it

THE PICTURE #
Durable execution
Durable execution read top to bottom as one story of a single workflow. Above the first note, every arrow reaching the payment provider is real work, and each result is written to the history before it is handed back. Below the notes the same first request appears again -- that is replay -- but the engine answers it from the history rather than the provider, so no second charge occurs. The last arrow is the frontier: the first step with no recorded answer, and so the first one that touches the world again. {"generator":"mermaid-svg-renderer@3.2.1","source":"../Socrates/.diagram-cache/_src/durable-execution.md","sourceIndex":1,"sourceLine":4,"sourceHash":"fa44e09f53c9ea6da786d3c0a6042f22d79c42b37a27efe8b847b7dd34edfab3","diagramType":"sequence","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":1123,"height":1100},"qa":{"passed":true,"findings":[]}} "Payment provider" 01 "Event history (replicated)" 02 "Execution engine" 03 "Workflow code" 04 the machine disappears here a new worker claims the workflow charge the card 1 call 2 confirmation id 3 append result, durably 4 committed 5 confirmation id 6 book the seat 7 charge the card (replay from line one) 8 is there a recorded result? 9 yes, confirmation id 10 confirmation id (no call made) 11 book the seat 12 call, for real this time 13
KINDSlifelineparticipantmessage

How to readread top to bottom as one story of a single workflow. Above the first note, every arrow reaching the payment provider is real work, and each result is written to the history before it is handed back. Below the notes the same first request appears again — that is replay — but the engine answers it from the history rather than the provider, so no second charge occurs. The last arrow is the frontier: the first step with no recorded answer, and so the first one that touches the world again.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

The surviving part of a crashed process was never its memory. It was the short, durable list of answers the outside world had already given it — and from that list, plus deterministic code, the entire lost state can be rebuilt by running the program again with its completed steps answered from the record. The cost of that trick is a real constraint on what the code is allowed to do, and a boundary at the edge where idempotency, not replay, is what prevents a duplicate charge.

g

Where to go next

ONWARD #
  • Why the determinism requirement forbids ordinary things like reading the clock, and what an engine substitutes instead.
  • How a workflow that is already mid-flight survives a deployment that changes its own sequence of steps.
  • Designing idempotent boundaries, so a repeated external call is harmless.
h

Key terms

TERMS #
TermWhat it means
Durable executionan execution model in which a program's progress is persisted as a record of results, so the program can be resumed on any machine after a failure.
Event historythe durable, ordered record of every result an execution received from outside itself.
Replayre-running a workflow from its first line while answering already-completed steps from the history rather than performing them.
Idempotency keya caller-supplied identifier that lets an external service recognise a repeated request as the same one and not perform it twice.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4