Step Functions Fundamentals
Step Functions Fundamentals
AWS Step Functions coordinate components of distributed applications through visual workflows.
Workflow Types
| Type | Max Duration | Price | Use Case |
|---|---|---|---|
| Standard | 1 year | Per state transition | Long-running, audit trails |
| Express | 5 minutes | Per execution + duration | High-volume, event processing |
State Machine Definition (ASL)
{
"Comment": "A simple workflow",
"StartAt": "ProcessOrder",
"States": {
"ProcessOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:ProcessOrder",
"Next": "CheckInventory"
},
"CheckInventory": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:CheckInventory",
"Next": "IsInStock"
},
"IsInStock": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.inStock",
"BooleanEquals": true,
"Next": "ShipOrder"
}
],
"Default": "NotifyCustomer"
},
"ShipOrder": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage",
"Parameters": {
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/123456789012/shipping-queue",
"MessageBody.$": "$.order"
},
"End": true
},
"NotifyCustomer": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:NotifyCustomer",
"End": true
}
}
}
State Types
| Type | Purpose |
|---|---|
| Task | Execute work (Lambda, API Gateway, etc.) |
| Choice | Branching logic (if/else) |
| Wait | Pause execution (seconds, timestamp) |
| Parallel | Execute multiple branches |
| Map | Iterate over a collection |
| Pass | Inject data or do nothing |
| Succeed | End workflow successfully |
| Fail | End workflow with error |
Error Handling and Retries
Error Handling and Retries
Try/Catch Pattern
{
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:xxx:function:my-function",
"Retry": [
{
"ErrorEquals": ["States.TaskFailed"],
"IntervalSeconds": 3,
"MaxAttempts": 3,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": ["States.ALL"],
"ResultPath": "$.error",
"Next": "HandleError"
}
],
"Next": "SuccessState"
}
Custom Error Codes
# Lambda function raising custom error
import json
def lambda_handler(event, context):
if event['amount'] > 1000:
raise Exception('ValidationError: Amount exceeds limit')
return {'processed': True}
"Retry": [
{
"ErrorEquals": ["ValidationError"],
"MaxAttempts": 0
},
{
"ErrorEquals": ["States.TaskFailed"],
"IntervalSeconds": 5,
"MaxAttempts": 3,
"BackoffRate": 2
}
]
Catch States
"Catch": [
{
"ErrorEquals": ["ValidationError"],
"Next": "ValidationFailed",
"ResultPath": "$.error"
},
{
"ErrorEquals": ["Lambda.ServiceException", "Lambda.SdkClientException"],
"Next": "ServiceError",
"ResultPath": "$.error"
},
{
"ErrorEquals": ["States.ALL"],
"Next": "GenericError",
"ResultPath": "$.error"
}
]
Parallel and Map States
Parallel and Map States
Parallel Execution
{
"Type": "Parallel",
"Branches": [
{
"StartAt": "ProcessPayment",
"States": {
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:xxx:function:ProcessPayment",
"End": true
}
}
},
{
"StartAt": "ReserveInventory",
"States": {
"ReserveInventory": {
"Type": "Task",
"Resource": "arn:aws:lambda:xxx:function:ReserveInventory",
"End": true
}
}
},
{
"StartAt": "SendConfirmation",
"States": {
"SendConfirmation": {
"Type": "Task",
"Resource": "arn:aws:lambda:xxx:function:SendEmail",
"End": true
}
}
}
],
"Next": "CombineResults"
}
Map State (Iterate)
{
"Type": "Map",
"ItemsPath": "$.orders",
"MaxConcurrency": 10,
"Iterator": {
"StartAt": "ProcessItem",
"States": {
"ProcessItem": {
"Type": "Task",
"Resource": "arn:aws:lambda:xxx:function:ProcessItem",
"End": true
}
}
},
"Next": "AggregateResults"
}
Map with Parameters
{
"Type": "Map",
"ItemsPath": "$.items",
"Parameters": {
"itemId.$": "$.itemId",
"itemName.$": "$.itemName",
"staticValue": "processed"
},
"MaxConcurrency": 5,
"Iterator": {
"StartAt": "Process",
"States": {
"Process": {
"Type": "Task",
"Resource": "arn:aws:lambda:xxx:function:Process",
"End": true
}
}
}
}
Step Functions Integration Patterns
Step Functions Integration Patterns
Direct AWS Service Integration
"PutItem": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:putItem",
"Parameters": {
"TableName": "MyTable",
"Item": {
"PK": {"S.$": "$.orderId"},
"SK": {"S": "ORDER"},
"Status": {"S": "PROCESSING"}
}
},
"Next": "NextStep"
}
SQS Integration
"SendMessage": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage",
"Parameters": {
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/123456789012/my-queue",
"MessageBody.$": "$.payload",
"MessageAttributes": {
"Priority": {
"DataType": "String",
"StringValue": "high"
}
}
}
}
Wait States
"WaitForCallback": {
"Type": "Wait",
"Seconds": 3600,
"Next": "CheckStatus"
}
"WaitUntil": {
"Type": "Wait",
"Timestamp": "2024-01-15T12:00:00Z",
"Next": "ProcessEvent"
}
Activity Workers
# External worker polling for tasks
import boto3
import json
sfn = boto3.client('stepfunctions')
# Get activity ARN
activity_arn = 'arn:aws:states:us-east-1:xxx:activity:my-activity'
# Poll for task
response = sfn.get_activity_task(
activityArn=activity_arn,
workerName='worker-1'
)
if 'taskToken' in response:
# Process task
result = {'status': 'completed', 'data': 'processed'}
# Send success
sfn.send_task_success(
taskToken=response['taskToken'],
output=json.dumps(result)
)
Step Functions Best Practices
Step Functions Best Practices
Architecture Patterns
┌─────────────────────────────────────────────────────────────┐
│ Order Processing Workflow │
├─────────────────────────────────────────────────────────────┤
│ │
│ Start ──▶ Validate ──▶ Check ──┬──▶ Ship (Parallel) │
│ │ │ ├─ Payment │
│ │ │ ├─ Inventory │
│ ▼ │ └─ Notification │
│ [Invalid] │ │
│ ▼
│ [Complete] │
└─────────────────────────────────────────────────────────────┘
Best Practices
- Use Express workflows for high-volume, short-duration tasks
- Use Standard workflows for auditable, long-running processes
- Implement retry policies instead of manual error handling
- Use Map state instead of parallel for dynamic iteration
- Pass data efficiently using ResultPath and OutputPath
- Keep states simple - one action per state
- Use activity workers for non-AWS integrations
Cost Optimization
| Type | Pricing |
|---|---|
| Standard | $0.025 per 1,000 state transitions |
| Express | $1.00 per 1M executions + $0.000025 per 1,000 GB-seconds |
# Create state machine
aws stepfunctions create-state-machine \
--name my-workflow \
--definition file://workflow.json \
--role-arn arn:aws:iam::xxx:role/StepFunctionsRole
# Start execution
aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:us-east-1:xxx:stateMachine:my-workflow \
--input '{"orderId": "123", "amount": 99.99}'
# Check execution history
aws stepfunctions describe-execution \
--execution-arn arn:aws:states:us-east-1:xxx:execution:my-workflow:xxx