Back to Blog

AWS Step Functions for the DVA-C02 Exam: Workflow Types, ASL, I/O Processing, Error Handling & Integration Patterns

A developer-level deep dive into AWS Step Functions for the AWS Certified Developer - Associate (DVA-C02) exam. Standard vs Express execution semantics, the Amazon States Language state types, the input/output processing pipeline, Retry and Catch error handling, the three service integration patterns (Request Response, .sync, .waitForTaskToken), Map vs Distributed Map, and the SAM, X-Ray, and TestState developer tooling.

By Sailor Team , September 30, 2026

The DVA-C02 expects you to recognize when AWS Step Functions is the right tool — “coordinate multiple steps with branching and error handling” points to a state machine, not a tangle of queues and glue code. That decision, and how Step Functions sits alongside SQS, SNS, and EventBridge, is covered in the event-driven architecture guide. This post goes one level deeper into the part the exam quietly assumes you can do: actually author, wire, and debug a state machine — the workflow types, the Amazon States Language, how data flows between states, how errors are handled declaratively, and how a task waits for a job or a human.

Get these mechanics right and a whole band of DVA-C02 questions — the ones with a snippet of state-machine JSON and a “what happens to the output” or “why does this retry” prompt — become straightforward.

Standard vs Express: The First Decision

Every state machine is created as one of two immutable types. The type is set at creation and cannot be changed afterward, so choosing correctly matters, and the exam probes the differences constantly.

DimensionStandardExpress
Maximum duration1 year5 minutes
Execution semanticsExactly-onceAsynchronous: at-least-once; Synchronous: at-most-once
Execution historyRecorded by Step Functions (visible in console/API), 90 daysOnly via CloudWatch Logs (must enable logging)
PricingPer state transitionPer number of executions + duration + memory
Service integration patternsRequest Response, Run a Job (.sync), Wait for Callback (.waitForTaskToken)Request Response only
Distributed Map / ActivitiesSupportedNot supported
Best forLong-running, auditable, non-idempotent work (payments, EMR jobs)High-volume, short, idempotent event processing

Two nuances candidates miss:

  • Express is not one flavor. Asynchronous Express returns immediately (you poll CloudWatch Logs for the result) and is at-least-once, so a step can run more than once — fine for idempotent work like a DynamoDB PutItem. Synchronous Express (started with StartSyncExecution, e.g. behind API Gateway) waits and returns the result and is at-most-once. The blanket “Express is at-least-once” you may have memorized is only half the story.
  • Standard is exactly-once, which is why it is the answer for non-idempotent actions — charging a card, starting a cluster — where running a step twice would be harmful.

The Amazon States Language and Its State Types

A state machine is defined in JSON using the Amazon States Language (ASL). You should be able to read a definition and name each state’s job. There are eight state types:

State typeWhat it does
TaskDoes work — invokes a Lambda function or an integrated AWS service
ChoiceBranches based on conditions (the if/switch of a workflow)
ParallelRuns multiple branches concurrently and joins their results
MapRuns the same steps for each item in an array
WaitDelays for a duration or until a timestamp
PassPasses input to output (optionally injecting fixed data); useful for testing
SucceedStops the execution successfully
FailStops the execution with an error name and cause

A minimal Task → Choice skeleton looks like this:

{
  "Comment": "Validate then charge",
  "StartAt": "Validate",
  "States": {
    "Validate": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": { "FunctionName": "validateOrder", "Payload.$": "$" },
      "Next": "IsValid" },
    "IsValid": { "Type": "Choice",
      "Choices": [ { "Variable": "$.valid", "BooleanEquals": true, "Next": "Charge" } ],
      "Default": "HandleFailure" },
    "Charge": { "Type": "Task", "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": { "FunctionName": "chargeCard", "Payload.$": "$" }, "End": true },
    "HandleFailure": { "Type": "Fail", "Cause": "ValidationFailed" }
  }
}

Note StartAt, the per-state Next/End, and the .$ suffix on Payload.$ — that suffix means “the value is a path into the state’s data,” which brings us to how data actually flows.

Processing Input and Output

This is the single most testable Step Functions mechanic at the developer level. Each state receives JSON input and produces JSON output, and for the classic JSONPath query language, five fields transform the data in a fixed order:

InputPath → Parameters → (task runs) → ResultSelector → ResultPath → OutputPath

  • InputPath — selects which part of the raw input to use.
  • Parameters — builds the exact structure sent to the task (this is where "Payload.$": "$" lives).
  • ResultSelector — picks/reshapes fields out of the task’s result.
  • ResultPath — decides where the result is placed relative to the original input. ResultPath: "$.result" keeps the input and nests the result under result; omit it and the result replaces the input.
  • OutputPath — filters the combined structure down to what the next state receives.

The one that trips people up is ResultPath: if a question shows an input object, a task result, and asks “what does the next state see,” the answer hinges on whether ResultPath merged the result into the input or overwrote it. Memorize the order and that rule.

Newer state machines can opt into JSONata instead of JSONPath by setting QueryLanguage. AWS now recommends JSONata for new workflows; it replaces the five-field pipeline with Arguments, Output, and Assign fields and lets you read state with $states.input. Existing state machines default to JSONPath for backward compatibility. Know that JSONata exists and is the recommended default going forward, but the JSONPath pipeline above is still the model most exam snippets use.

Error Handling: Retry and Catch

Step Functions gives you declarative error handling so you do not scatter retry loops through your Lambda code. Two fields on a Task (or Parallel/Map) state do the work.

Retry retries the state on matching errors with exponential backoff:

"Retry": [
  { "ErrorEquals": ["States.TaskFailed"],
    "IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 2.0 }
]

IntervalSeconds is the first wait, MaxAttempts the retry count, and BackoffRate the multiplier applied each attempt (2, then 4, then 8 seconds here). This mirrors the retry-with-backoff pattern you would otherwise hand-code — see the SDK retries and exponential backoff guide — but managed by the workflow.

Catch routes to a fallback state when an error is not (or is no longer) retried:

"Catch": [
  { "ErrorEquals": ["States.ALL"], "ResultPath": "$.error", "Next": "Cleanup" }
]

The exam expects you to know the predefined error names: States.ALL (any error), States.TaskFailed, States.Timeout, States.Permissions, and others. States.ALL must be the last retrier or catcher because it matches everything. Using ResultPath inside Catch to preserve the error under $.error (rather than discarding the original input) is a common “which output” question.

Service Integration Patterns

A Task can call a service in one of three integration patterns, chosen by a suffix on the Resource ARN. This is heavily tested, and each pattern behaves differently.

PatternARN suffixBehavior
Request Response (default)(none)Call the service, get the HTTP response, move to the next state immediately
Run a Job.syncCall the service and wait for the job to complete before continuing
Wait for Callback.waitForTaskTokenPause until an external process returns a task token

Run a Job (.sync) is for services with long-running work — AWS Batch, ECS/Fargate tasks, AWS Glue, EMR, a nested Step Functions execution. arn:aws:states:::batch:submitJob.sync submits the job and the state pauses until Batch reports done.

Wait for Callback (.waitForTaskToken) is the pattern for human approvals, third-party callbacks, and legacy integrations. You embed a task token in the outbound call and the state pauses — potentially for up to the one-year execution limit — until something calls back:

"WaitForApproval": {
  "Type": "Task",
  "Resource": "arn:aws:states:::sqs:sendMessage.waitForTaskToken",
  "Parameters": {
    "QueueUrl": "https://sqs.us-east-1.amazonaws.com/123456789012/approvals",
    "MessageBody": { "orderId.$": "$.orderId", "TaskToken.$": "$$.Task.Token" }
  },
  "Next": "Fulfill"
}

The token comes from the Context object via $$.Task.Token (the double $$ accesses execution context, not state data). The external worker resumes the workflow by calling SendTaskSuccess (with a result payload) or SendTaskFailure. To avoid a task hanging forever, set a HeartbeatSeconds timeout and have the worker call SendTaskHeartbeat; miss the heartbeat window and the task fails with States.Timeout.

Critical exam fact: Express workflows support only Request Response. Neither .sync nor .waitForTaskToken works in Express. If a scenario needs to wait for a job or a callback, the answer is a Standard workflow.

Map and Distributed Map

A Map state runs the same steps for each element of an input array. The inline Map runs iterations within the parent execution and is fine for modest arrays. Distributed Map is a mode built for massive parallelism — up to 10,000 parallel child executions and datasets read straight from Amazon S3 (millions of objects) — and it is Standard-only (Express does not support Distributed Map). For the DVA-C02, know that inline Map handles ordinary “process each item” work; the large-scale, S3-driven fan-out architecture is more of a Solutions Architect Professional concern, covered in the SAP-C02 serverless architecture patterns guide. Keep your developer focus on the inline mechanics.

Developer Tooling: SAM, X-Ray, and TestState

Building and shipping state machines is squarely a developer task, so know the tooling:

  • AWS SAM defines a state machine as AWS::Serverless::StateMachine, with the ASL kept in a separate definition file and referenced by DefinitionUri — the same infrastructure-as-code workflow as the rest of your serverless app. See the SAM serverless deployments guide for the deployment mechanics.
  • AWS X-Ray integrates with Step Functions for distributed tracing across the workflow and its downstream services — the answer when a question asks how to trace a slow or failing multi-step workflow. It complements the CloudWatch metrics and logs covered in the monitoring and troubleshooting guide.
  • TestState is an API that tests a single state in isolation — you pass sample input and inspect the output and the applied input/output processing without running the whole machine. It is the fast way to debug a ResultPath or Choice rule.
  • Versions and aliases let you publish immutable versions of a state machine and shift traffic with an alias, mirroring the pattern you already use for Lambda versions, aliases, and concurrency.

Decision Cheat Sheet and Exam Traps

Scenario wordingPoints to
”Non-idempotent step must never run twice”Standard (exactly-once)
“High-volume, short, idempotent event processing, cheapest”Express (asynchronous)
“Synchronous response behind API Gateway”Synchronous Express (StartSyncExecution)
“Wait for an AWS Batch / ECS / Glue job to finish”.sync on a Standard workflow
”Pause for a human approval or third-party callback”.waitForTaskToken + SendTaskSuccess (Standard)
“Preserve the original input alongside a task’s result”ResultPath merges the result
”Retry transient failures automatically with backoff”Retry with BackoffRate
”Send failures to a cleanup branch”Catch with States.ALL last

Recurring traps: choosing Express when the workflow needs .sync or .waitForTaskToken (unsupported in Express); forgetting that ResultPath omitted means the result replaces the input; putting States.ALL before more specific error matchers; and assuming Standard and Express are interchangeable after creation (the type is immutable).

Frequently Asked Questions

When should I use Standard vs Express workflows on the DVA-C02?

Use Standard for long-running (up to a year), auditable, non-idempotent work where exactly-once matters — payments, orchestrating cluster jobs — and whenever you need the .sync or .waitForTaskToken integration patterns. Use Express for high-volume, short (≤5 minute), idempotent event processing where cost and throughput matter. Remember Synchronous Express is at-most-once while Asynchronous Express is at-least-once.

What is the difference between InputPath, Parameters, ResultSelector, ResultPath, and OutputPath?

They are the five JSONPath fields that transform data through a state, applied in that order. InputPath selects input; Parameters builds what the task receives; ResultSelector reshapes the task result; ResultPath decides where the result is placed relative to the input (merge vs replace); OutputPath filters what the next state gets. ResultPath is the most commonly tested because it controls whether the original input survives.

How do Retry and Catch differ?

Retry re-attempts the same state on matching errors using IntervalSeconds, MaxAttempts, and BackoffRate for exponential backoff. Catch gives up on the state and transitions to a fallback state when an error matches. A state can have both — retry first, then catch what still fails. List States.ALL last in either.

What does .waitForTaskToken do?

It pauses a task until an external process calls back. Step Functions passes a task token (via $$.Task.Token) in the outbound request; the worker later calls SendTaskSuccess or SendTaskFailure with that token to resume the workflow. Use HeartbeatSeconds and SendTaskHeartbeat to avoid waiting indefinitely. It is supported only in Standard workflows.

Can Express workflows use the .sync or callback patterns?

No. Express workflows support only the Request Response pattern. If you need to wait for a job (.sync) or a callback (.waitForTaskToken), you must use a Standard workflow.

Conclusion

Step Functions questions on the DVA-C02 reward developers who can read a state machine, not just name the service. Anchor on four things: the Standard vs Express split (exactly-once vs at-least-once/at-most-once, and the fact that only Standard supports .sync and .waitForTaskToken); the ASL state types and how a Task calls work; the input/output pipeline, especially how ResultPath merges or replaces; and the error-handling fields Retry and Catch with the predefined error names. Layer on the integration patterns and the SAM/X-Ray/TestState tooling and you can answer the snippet-based questions with confidence.

The reliable way to make these mechanics automatic is timed practice on questions that show real ASL and ask “what happens next.” Sailor.sh’s AWS Certified Developer - Associate (DVA-C02) Certification-Ready Mock Exam Bundle drills exactly these serverless-orchestration scenarios with explanations that reinforce why an output looks the way it does or why a workflow retried. Pair the mocks with the DVA-C02 exam guide for 2026 and the study plan, and treat every Step Functions question you miss as a chance to sharpen your reading of the state language.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now