Skip to content
Aryan Gupta
← Writing

Workflow orchestration and durable execution

  • Temporal
  • Serverless Workflow
  • Go
  • Workflows

Lending journeys do not fit the request model. An application waits on document uploads, bureau pulls, underwriting decisions, and applicant follow-up. Elapsed time is hours or days, and the process has to survive deploys. If progress lives in a request, a crash loses the journey. If it lives in a hand-rolled status column and a sweeper cron, you have invented a state machine under pressure.

On Studio, we put that progress in workflow history instead.

Two layers, one runtime

The orchestration layer pairs two things: Temporal for durable execution, and the Serverless Workflow spec as the definition language. Temporal owns survival — crashes, long waits, retries, replay. Serverless Workflow owns expressiveness — states, events, parallel branches, error handling, compensation. The engine's job is to parse a definition, map each state onto Temporal workflows and activities, and keep the durability guarantees intact.

That mapping is the interesting part. The models are close but not identical. Event-based transitions, parallel states, and compensation flows do not drop one-to-one onto Temporal primitives. Error semantics are the same story twice: the spec has an error model, Temporal has retries and propagation, and composing them so the definition's behaviour is what actually runs takes more edge cases than the happy path suggests.

Who authors what

The product surface on top is a visual canvas. Operations, product, and analysts drag activities from a library — call this API, apply this rule, send this notification — and stitch them into a journey. Engineers own the activity library: what is possible. Business teams own composition: what actually runs. Publishing a composed journey does not require a deploy of the platform; adding a new activity does.

That split is what makes the system useful. Without it, every process change is still a code change.

What changes about failure

Durable execution does not remove failure handling. It relocates it. The step becomes the unit of retry, non-retryable errors have to be named, and workflow code has to stay deterministic so replay stays honest. Versioning matters too: journeys still in flight when you change their shape need gated changes, not a blind deploy.

The trade is explicit policy at authoring time instead of recovery code written after an incident. Working on that layer is mostly that trade, over and over — and it has been worth making carefully.