AWS Step Functions Cheat Sheet
ASL state types, error handling, and CLI/SDK commands for building and running serverless workflow orchestrations.
Basic State Machine (ASL)
A minimal state machine with a Task and a Choice state.
{ "Comment": "Order processing workflow", "StartAt": "ValidateOrder", "States": { "ValidateOrder": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:validateOrder", "Next": "IsValid" }, "IsValid": { "Type": "Choice", "Choices": [ { "Variable": "$.valid", "BooleanEquals": true, "Next": "ProcessPayment" } ], "Default": "RejectOrder" }, "ProcessPayment": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:charge", "End": true }, "RejectOrder": { "Type": "Fail", "Error": "OrderInvalid", "Cause": "Validation failed" } }}
Retry & Catch on a Task
Standard error-handling block for a Task state.
{ "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:charge", "Retry": [ { "ErrorEquals": ["States.TaskFailed"], "IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 2.0 } ], "Catch": [ { "ErrorEquals": ["States.ALL"], "ResultPath": "$.error", "Next": "NotifyFailure" } ], "Next": "ShipOrder"}
Map State for Fan-Out
Process each item in an array concurrently.
{ "Type": "Map", "ItemsPath": "$.items", "MaxConcurrency": 5, "Iterator": { "StartAt": "ProcessItem", "States": { "ProcessItem": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:processItem", "End": true } } }, "End": true}
Start & Describe an Execution (CLI)
Kick off a workflow run and check its status.
aws stepfunctions start-execution \ --state-machine-arn arn:aws:states:us-east-1:123456789012:stateMachine:OrderFlow \ --input '{"orderId": "o-123"}'aws stepfunctions describe-execution \ --execution-arn arn:aws:states:us-east-1:123456789012:execution:OrderFlow:abc123
ASL State Types
The eight state types you can use in a state machine definition.
- Task- invokes a Lambda, activity, or AWS service integration
- Choice- branches based on conditions evaluated against the input
- Parallel- runs fixed branches concurrently
- Map- iterates over an array, running a sub-workflow per item
- Wait- pauses for a duration or until a timestamp
- Pass- passes input to output, optionally injecting data
- Succeed / Fail- terminal states that end the execution
Distributed Map over S3 Objects
Distributed Map (Standard workflows) fans out to millions of items by reading a manifest or listing an S3 prefix directly, far beyond the ~40 concurrent child limit of the regular Map state.
{ "Type": "Map", "ItemProcessor": { "ProcessorConfig": { "Mode": "DISTRIBUTED", "ExecutionType": "STANDARD" }, "StartAt": "ProcessFile", "States": { "ProcessFile": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:processFile", "End": true } } }, "ItemReader": { "Resource": "arn:aws:states:::s3:listObjectsV2", "Parameters": { "Bucket": "my-input-bucket", "Prefix": "raw/" } }, "MaxConcurrency": 1000, "ResultWriter": { "Resource": "arn:aws:states:::s3:putObject", "Parameters": { "Bucket": "my-output-bucket", "Prefix": "results/" } }, "End": true}
Callback Pattern with waitForTaskToken
Pause a workflow until an external system (human approval, third-party webhook) calls back with the task token — the standard way to bridge async/human-in-the-loop steps.
{ "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken", "Parameters": { "FunctionName": "requestApproval", "Payload": { "taskToken.$": "$$.Task.Token", "orderId.$": "$.orderId" } }, "TimeoutSeconds": 3600, "Next": "ShipOrder"}
Resuming from the Callback Side (SDK)
The external system calls SendTaskSuccess/SendTaskFailure with the token it received to unblock the waiting execution.
import boto3sfn = boto3.client("stepfunctions")# On approvalsfn.send_task_success( taskToken=received_token, output='{"approved": true}')# On rejection / business errorsfn.send_task_failure( taskToken=received_token, error="ApprovalRejected", cause="Manager denied the request")# Keep a long-running human task alive past the default token TTLsfn.send_task_heartbeat(taskToken=received_token)
JSONata Expressions & Intrinsic Functions
Newer state machines can use full JSONata (QueryLanguage: JSONata) instead of JSONPath, enabling inline transforms without extra Pass states.
{ "QueryLanguage": "JSONata", "StartAt": "ComputeTotal", "States": { "ComputeTotal": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:charge", "Arguments": { "orderId": "{% $states.input.orderId %}", "total": "{% $sum($states.input.items.price) * 1.08 %}" }, "Output": "{% { 'chargedAmount': $states.result.amount } %}", "End": true } }}
Advanced Execution Concepts
Behavior and limits that matter once workflows get complex or high-volume.
- Execution history limit (Standard)25,000 events per execution; deeply looping or highly fan-out workflows can hit this — use Distributed Map or split into child executions
- Express workflow loggingmust be explicitly enabled to CloudWatch Logs (no free execution history in the console) since Express is optimized for high volume, not per-run auditability
- Nested/child workflowsa Task state can invoke another state machine (arn:aws:states:::states:startExecution), useful for reusable sub-processes and staying under history limits
- Service integration patternsRequest-Response, Run a Job (.sync), and Wait for Callback (.waitForTaskToken) — pick .sync for AWS Batch/ECS/EMR jobs to natively await completion without polling
- Local testingthe Step Functions Local Docker container and the state machine "TestState" API let you unit test a single state's logic before a full deploy
- IAM least privilegeeach Resource ARN referenced in the ASL needs a matching iam:PassRole/invoke permission on the state machine's execution role — wildcard roles are the most common Step Functions security finding
Prefer Express workflows for high-volume, short-duration event processing (sub-5-min, at-least-once) and Standard workflows for anything needing exactly-once semantics and execution history longer than CloudWatch Logs retention.