state
State machine foundation for durable workflow execution with automatic persistence
state
State machines as the foundation for durable workflow execution - enabling complex multi-step processes with automatic state persistence, transitions, and error recovery.
Overview
The state primitive is the foundational state machine that powers durable workflow execution. Every workflow (see workflows) is fundamentally a state machine that transitions through well-defined states as it executes.
Core Principle: Workflows ARE Code Functions (see functions) with state machines that enable:
- State Persistence - Automatic state storage between steps
- State Transitions - Well-defined progression through workflow stages
- Error Recovery - Resume from last successful state after failures
- Long-Running - Maintain state for hours, days, or weeks
This makes state machines the foundational primitive for orchestrating complex business processes that require durability and reliability.
State Machine Fundamentals
Finite State Machines (FSM)
Workflows are finite state machines with well-defined states and transitions:
import { workflow, state } from 'sdk.do'
// Order processing state machine
workflow('process-order', async ({ order }) => {
// State: PENDING → VALIDATED
const validated = await state.transition('PENDING', 'VALIDATED', async () => {
await validateOrder(order)
return { orderId: order.id, valid: true }
})
// State: VALIDATED → PAYMENT_PROCESSING
const payment = await state.transition('VALIDATED', 'PAYMENT_PROCESSING', async () => {
return await processPayment(order)
})
// State: PAYMENT_PROCESSING → PAYMENT_COMPLETED
await state.transition('PAYMENT_PROCESSING', 'PAYMENT_COMPLETED', async () => {
await confirmPayment(payment)
})
// State: PAYMENT_COMPLETED → SHIPPED
await state.transition('PAYMENT_COMPLETED', 'SHIPPED', async () => {
await createShipment(order)
})
// Final state: COMPLETED
await state.transition('SHIPPED', 'COMPLETED', async () => {
await sendConfirmation(order)
})
})State Transitions
State transitions define valid progressions through workflow stages:
import { state, workflow } from 'sdk.do'
// Define state machine
const orderStateMachine = state.machine({
initial: 'PENDING',
states: {
PENDING: {
on: {
VALIDATE: 'VALIDATING',
},
},
VALIDATING: {
on: {
SUCCESS: 'VALIDATED',
FAILURE: 'VALIDATION_FAILED',
},
},
VALIDATED: {
on: {
PROCESS_PAYMENT: 'PROCESSING_PAYMENT',
},
},
PROCESSING_PAYMENT: {
on: {
SUCCESS: 'PAYMENT_COMPLETED',
FAILURE: 'PAYMENT_FAILED',
},
},
PAYMENT_COMPLETED: {
on: {
SHIP: 'SHIPPING',
},
},
SHIPPING: {
on: {
SUCCESS: 'COMPLETED',
FAILURE: 'SHIPPING_FAILED',
},
},
COMPLETED: {
type: 'final',
},
VALIDATION_FAILED: {
type: 'final',
},
PAYMENT_FAILED: {
on: {
RETRY: 'PROCESSING_PAYMENT',
},
},
SHIPPING_FAILED: {
on: {
RETRY: 'SHIPPING',
},
},
},
})
// Use in workflow
workflow('process-order', async ({ order }) => {
const machine = await orderStateMachine.create({ order })
// Execute state transitions
await machine.send('VALIDATE')
await machine.send('PROCESS_PAYMENT')
await machine.send('SHIP')
return machine.state
})State Persistence
State is automatically persisted between workflow steps, enabling durable execution:
Automatic Persistence
import { workflow, state } from 'sdk.do'
workflow('long-running-process', async ({ data }) => {
// Step 1: Initialize state (persisted)
await state.set('current', 'STEP_1')
const step1Result = await performStep1(data)
await state.set('step1Result', step1Result)
// If process crashes here, workflow resumes from Step 2
// State is automatically restored
// Step 2: Use persisted state (persisted)
await state.set('current', 'STEP_2')
const step1Data = await state.get('step1Result')
const step2Result = await performStep2(step1Data)
await state.set('step2Result', step2Result)
// Step 3: Complete (persisted)
await state.set('current', 'STEP_3')
const step2Data = await state.get('step2Result')
return await performStep3(step2Data)
})State Recovery
Workflows automatically recover from failures using persisted state:
import { workflow, state } from 'sdk.do'
workflow('resilient-process', async ({ order }) => {
// Check current state
const currentState = await state.get('current')
// Resume from last successful state
if (currentState === 'PAYMENT_FAILED') {
// Retry payment
const payment = await processPayment(order)
await state.set('payment', payment)
await state.set('current', 'PAYMENT_COMPLETED')
}
if (currentState === 'PAYMENT_COMPLETED') {
// Continue to shipping
const payment = await state.get('payment')
await createShipment(order, payment)
await state.set('current', 'SHIPPED')
}
// Workflow continues from current state
})State Snapshots
Capture complete state snapshots for rollback:
import { workflow, state } from 'sdk.do'
workflow('transaction-workflow', async ({ transaction }) => {
// Snapshot state before risky operation
const snapshot = await state.snapshot()
try {
// Attempt risky operation
await performRiskyOperation(transaction)
await state.set('status', 'COMPLETED')
} catch (error) {
// Rollback to snapshot on failure
await state.restore(snapshot)
await state.set('status', 'FAILED')
throw error
}
})State Patterns
Hierarchical State Machines (Statecharts)
Complex workflows use nested state machines:
import { state } from 'sdk.do'
const orderStatechart = state.machine({
initial: 'PROCESSING',
states: {
PROCESSING: {
initial: 'VALIDATING',
states: {
VALIDATING: {
on: { SUCCESS: 'PAYMENT' },
},
PAYMENT: {
initial: 'AUTHORIZING',
states: {
AUTHORIZING: {
on: { SUCCESS: 'CAPTURING' },
},
CAPTURING: {
on: { SUCCESS: '#PROCESSING.SHIPPING' },
},
},
},
SHIPPING: {
on: { SUCCESS: '#COMPLETED' },
},
},
},
COMPLETED: {
type: 'final',
},
},
})Parallel States
Execute multiple state machines concurrently:
import { state, workflow } from 'sdk.do'
workflow('onboard-customer', async ({ customer }) => {
// Run multiple state machines in parallel
const [account, profile, notifications] = await Promise.all([
// Account setup state machine
state
.machine({
initial: 'CREATING_ACCOUNT',
states: {
CREATING_ACCOUNT: {
on: { SUCCESS: 'VERIFYING_EMAIL' },
},
VERIFYING_EMAIL: {
on: { SUCCESS: 'ACCOUNT_READY' },
},
ACCOUNT_READY: {
type: 'final',
},
},
})
.execute({ customer }),
// Profile setup state machine
state
.machine({
initial: 'GATHERING_INFO',
states: {
GATHERING_INFO: {
on: { SUCCESS: 'PROFILE_COMPLETE' },
},
PROFILE_COMPLETE: {
type: 'final',
},
},
})
.execute({ customer }),
// Notifications setup state machine
state
.machine({
initial: 'SETTING_PREFERENCES',
states: {
SETTING_PREFERENCES: {
on: { SUCCESS: 'NOTIFICATIONS_READY' },
},
NOTIFICATIONS_READY: {
type: 'final',
},
},
})
.execute({ customer }),
])
return { account, profile, notifications }
})Conditional States
States with conditional transitions:
import { state, workflow } from 'sdk.do'
workflow('approve-contract', async ({ contract }) => {
const machine = state.machine({
initial: 'PENDING_REVIEW',
states: {
PENDING_REVIEW: {
on: {
SUBMIT: [
// Guard: Check if amount requires executive approval
{
target: 'EXECUTIVE_REVIEW',
cond: (ctx) => ctx.contract.amount > 100000,
},
// Otherwise, standard approval
{
target: 'MANAGER_REVIEW',
},
],
},
},
MANAGER_REVIEW: {
on: {
APPROVE: 'APPROVED',
REJECT: 'REJECTED',
},
},
EXECUTIVE_REVIEW: {
on: {
APPROVE: 'APPROVED',
REJECT: 'REJECTED',
ESCALATE: 'BOARD_REVIEW',
},
},
BOARD_REVIEW: {
on: {
APPROVE: 'APPROVED',
REJECT: 'REJECTED',
},
},
APPROVED: {
type: 'final',
},
REJECTED: {
type: 'final',
},
},
})
return await machine.execute({ contract })
})State in Durable Workflows
State machines enable durable execution in workflows:
Workflow State Persistence
import { workflow, state } from 'sdk.do'
workflow('employee-onboarding', async ({ employee }) => {
// Day 1: Welcome
await state.transition('HIRED', 'WELCOMED', async () => {
await sendWelcomeEmail(employee)
})
// Wait 7 days (state persisted during sleep)
await sleep({ days: 7 })
// Day 8: First check-in (resumed from persisted state)
await state.transition('WELCOMED', 'FIRST_CHECKIN', async () => {
await scheduleCheckIn(employee)
})
// Wait 30 days
await sleep({ days: 30 })
// Day 38: First review (resumed from persisted state)
await state.transition('FIRST_CHECKIN', 'REVIEWED', async () => {
await scheduleReview(employee)
})
// Wait 60 days
await sleep({ days: 60 })
// Day 98: Onboarding complete
await state.transition('REVIEWED', 'ONBOARDED', async () => {
await completeOnboarding(employee)
})
})Human-in-the-Loop States
Workflows wait in specific states for human decisions:
import { workflow, state, user } from 'sdk.do'
workflow('purchase-approval', async ({ purchase }) => {
// Automatic state: Validate
await state.transition('PENDING', 'VALIDATED', async () => {
await validatePurchase(purchase)
})
// Human state: Await approval (workflow pauses here)
const approval = await state.transition('VALIDATED', 'AWAITING_APPROVAL', async () => {
return await user.requestApproval({
type: 'purchase-approval',
data: { purchaseId: purchase.id },
timeout: { hours: 48 },
})
})
// Conditional transition based on approval
if (approval.approved) {
await state.transition('AWAITING_APPROVAL', 'APPROVED', async () => {
await processPurchase(purchase)
})
} else {
await state.transition('AWAITING_APPROVAL', 'REJECTED', async () => {
await notifyRejection(purchase)
})
}
})State Observability
Track state transitions for monitoring and debugging:
State History
import { state, workflow } from 'sdk.do'
workflow('order-fulfillment', async ({ order }) => {
// Enable state history tracking
await state.enableHistory()
await state.transition('RECEIVED', 'PROCESSING', async () => {
await processOrder(order)
})
await state.transition('PROCESSING', 'SHIPPED', async () => {
await shipOrder(order)
})
// Get state transition history
const history = await state.getHistory()
// [
// { from: 'RECEIVED', to: 'PROCESSING', at: '2025-01-01T10:00:00Z' },
// { from: 'PROCESSING', to: 'SHIPPED', at: '2025-01-01T11:00:00Z' }
// ]
return history
})State Metrics
import { state, send } from 'sdk.do'
// Track state transitions for analytics
state.on('transition', async ({ from, to, duration }) => {
await send($.Analytics.track, {
event: 'state.transition',
data: {
from,
to,
duration,
workflow: 'order-processing',
},
})
})
// Track state failures
state.on('failure', async ({ state, error }) => {
await send($.Analytics.track, {
event: 'state.failure',
data: {
state,
error: error.message,
workflow: 'order-processing',
},
})
})SDK Object Integration
State machines integrate with workflow triggers and event handlers:
import { state, every, on, workflow } from 'sdk.do'
// EVERY - Scheduled state machine execution (every is 1 of 8 core SDK objects)
every('daily at 9am', async () => {
const machine = state.machine({
initial: 'GATHERING_DATA',
states: {
GATHERING_DATA: {
on: { SUCCESS: 'GENERATING_REPORT' },
},
GENERATING_REPORT: {
on: { SUCCESS: 'SENDING_REPORT' },
},
SENDING_REPORT: {
on: { SUCCESS: 'COMPLETED' },
},
COMPLETED: {
type: 'final',
},
},
})
await machine.execute()
})
// ON - Event-driven state transitions (on is 1 of 8 core SDK objects)
on($.Order.created, async ({ order }) => {
const machine = state.machine({
initial: 'VALIDATING',
states: {
VALIDATING: {
on: { SUCCESS: 'PROCESSING' },
},
PROCESSING: {
on: { SUCCESS: 'SHIPPED' },
},
SHIPPED: {
on: { SUCCESS: 'COMPLETED' },
},
COMPLETED: {
type: 'final',
},
},
})
await machine.execute({ order })
})Core Capabilities
- Finite State Machines - Well-defined states and transitions
- State Persistence - Automatic state storage between steps
- Error Recovery - Resume from last successful state
- Hierarchical States - Nested state machines (statecharts)
- Parallel States - Concurrent state machine execution
- Conditional Transitions - Guards for state transitions
- State History - Track state transition history
- Durable Execution - Long-running workflows with persistent state
Access Methods
SDK
TypeScript/JavaScript library for state machine management
await state.transition('PENDING', 'PROCESSING', async () => {
/* ... */
})CLI
Command-line tool for state operations
do state get workflow-123 --key currentAPI
REST/RPC endpoints for state management
curl -X POST https://api.do/v1/state/workflow-123/transition -d '{"from":"PENDING","to":"PROCESSING"}'MCP
Model Context Protocol for AI-driven state operations
Transition workflow state from PENDING to PROCESSINGRelated Primitives
Parent Concept
- workflows - Workflows ARE code functions with state machines
SDK Object Mappings
- every - Time-based state machine execution (SDK object - 1 of 8 core)
- on - Event-driven state transitions (SDK object - 1 of 8 core)