Temporal DSL
Temporal DSL: A Domain-Specific Language for Temporal Workflows#
Temporal is a powerful platform for building reliable, fault-tolerant applications. Its workflows allow developers to orchestrate complex processes with ease, ensuring resilience, retries, and visibility into long-running operations. However, writing Temporal workflows typically requires a fair amount of boilerplate code and deep familiarity with Temporal’s SDKs.
This is where Temporal DSL comes in.
What is Temporal DSL?#
Temporal DSL implements the powerful Serverless Workflow domain-specific language (DSL) that allows developers to define Temporal workflows using YAML. Instead of manually coding every step in TypeScript, Go, or Java, users can write a simple, declarative specification that describes:
- The sequence of activities
- Conditions and branching logic
- Parallel execution paths
- Retries, error handling, and compensation
By representing workflows in a human-readable format, teams can visualise, share, and maintain workflows without needing every collaborator to be an expert in Temporal SDKs.
Why is this useful?#
- Lower barrier to entry YAML is easier for newcomers than Temporal SDKs. Product managers, QA engineers, and business analysts can contribute to workflow definitions without needing to learn Temporal code.
- Readable and shareable workflows The declarative format doubles as documentation. A YAML file describing a workflow is easy to review in code reviews, easy to share across teams, and easy to version control.
- Faster iteration Developers can prototype workflows rapidly by editing YAML files instead of writing and compiling code. This makes experimenting with workflow design much quicker.
- Consistency across teams Standardising workflow definitions in YAML reduces variability and makes workflows portable across different services or teams.
Example#
Here is the Money Transfer Demo in Temporal DSL:
document:
dsl: 1.0.0
namespace: default
name: money-transfer
version: 0.0.1
title: Money Transfer Demo
summary: Temporal's world-famous Money Transfer Demo, in DSL form
do:
# Configure a listener to query the workflow state
- queryState:
listen:
to:
one:
with:
id: transferStatus
type: query
datacontenttype: application/json
# The JSON object returned by the query
data: |
approvalTime: {{ .stateApprovalTime }}
chargeResult:
chargeId: {{ .stateChargeId }}
progressPercentage: {{ .stateProgressPercentage }}
transferState: {{ .stateTransferState }}
workflowStatus: {{ .stateWorkflowStatus }}
# Configure the default state object
- setup:
set:
idempotencyKey: "{{ uuidv4 }}"
stateApprovalTime: 30
stateChargeId: "{{ uuidv4 }}"
stateProgressPercentage: 0
stateTransferState: starting
stateWorkflowStatus: ""
# Validate the transfer request
- validate:
call: http
with:
method: post
endpoint: http://server:3000/validate
# Update the workflow's state
- updateState:
set:
stateProgressPercentage: 25
stateTransferState: running
# Take the money out of the sender's account
- withdraw:
call: http
with:
method: post
endpoint: http://server:3000/withdraw
headers:
content-type: application/json
body: >
{
"amount": {{ .amount }},
"attempt": {{ ._ta_attempt }},
"idempotencyKey": {{ .idempotencyKey | quote }},
"name": {{ ._tw_workflow_type_name | quote }}
}
# Update the workflow's state again
- updateState:
set:
stateProgressPercentage: 50
# Send the money to the recipient
- deposit:
call: http
with:
method: post
endpoint: http://server:3000/deposit
headers:
content-type: application/json
body: >
{
"amount": {{ .amount }},
"attempt": {{ ._ta_attempt }},
"idempotencyKey": {{ .idempotencyKey | quote }},
"name": {{ ._tw_workflow_type_name | quote }}
}
# We're nearly there
- updateState:
set:
stateProgressPercentage: 75
# Finally, send notification of the transfer
- sendNotification:
call: http
with:
method: post
endpoint: http://server:3000/notify
headers:
content-type: application/json
body: >
{
"amount": {{ .amount }},
"fromAccount": {{ .fromAccount | quote }},
"toAccount": {{ .toAccount | quote }}
}
# We're complete
- updateState:
set:
stateProgressPercentage: 100
stateTransferState: finished
Key Features#
- Sequential execution: Activities run one after the other.
- Parallel branches: Define multiple branches to run concurrently.
- Conditionals: Support for if/else-style logic.
- Retries & error handling: Declarative syntax for resilience.
- Composable workflows: Reference reusable workflows inside larger ones.
Real-world Use Cases#
- E-commerce – Define checkout, payment, and shipping workflows without writing boilerplate code.
- Data pipelines – Orchestrate ETL steps declaratively.
- DevOps automation – Run build, deploy, and rollback pipelines as workflows.
- Human-in-the-loop processes – Model approval chains, customer onboarding, or know-your-customer (KYC) checks.
Benefits for Temporal Users#
- Simplified onboarding – New users don’t need to learn SDKs immediately.
- Improved collaboration – Business and engineering teams can collaborate on workflow design.
- Clear documentation – YAML workflows act as living specifications.
- Rapid prototyping – Test ideas quickly before formalising workflows in code.
Temporal DSL brings a declarative, human-readable way to define Temporal workflows. By leveraging YAML, it reduces friction for new users, accelerates workflow development, and makes Temporal even more accessible to teams beyond core engineering.
👉 Explore it here: github.com/mrsimonemms/temporal-dsl
Language
About the Author

Simon Emms
Staff Solutions Architect, EMEA