ThisCalculator

Everyday

AWS Step Functions Webhook Callbacks for Long Workflows

Updated · Standard formula, shown below

AWS Step Functions Webhook Callbacks for Long Workflows

Yes, AWS Step Functions webhook callbacks are a built-in mechanism for orchestrating long-running workflows by pausing a state machine and waiting for an external system to resume it. You configure a task state with a callback token, and the external system uses that token to send a success or failure response, which tells Step Functions to continue the workflow.

What Are Webhook Callbacks in Step Functions?

Step Functions is AWS’s serverless orchestration service that lets you build state machines to coordinate multiple AWS services and external applications. Normally, a task state runs a synchronous operation—like invoking a Lambda function—and waits for that operation to complete. But many real-world processes take minutes, hours, or even days: a human approval, a third-party payment, a long-running batch job, or a manual data review.

Webhook callbacks (also called “wait for callback� or “task tokens�) solve this by decoupling the workflow from the execution time of the external process. When a task state is configured to wait for a callback, Step Functions generates a unique token and passes it to the external system. The state machine then pauses at that step, holding its place in the execution history. The external system performs its work and later calls the SendTaskSuccess or SendTaskFailure API with that token. Step Functions resumes the workflow at exactly the next state, using the output provided in the callback.

This pattern is distinct from a simple HTTP webhook where an external service calls a URL. In Step Functions, the callback is an API call to AWS, not an inbound HTTP request. The token acts as a secure reference to the specific execution and state, so the external system doesn’t need to know the workflow’s internal structure.

How the Callback Mechanism Works

To use a callback, you configure a task state (like a Lambda function or an Activity) with "WaitForCallback": true in the state definition. When the state runs, Step Functions creates a token and passes it to the task. For a Lambda function, the token appears in the event payload; for an Activity, it’s included in the activity task response.

The external system then performs its work. When finished, it calls one of these APIs:

  • SendTaskSuccess – resumes the workflow with a specified output (JSON).
  • SendTaskFailure – fails the state, optionally with an error code and cause.
  • SendTaskHeartbeat – sends a heartbeat to indicate the task is still alive (used with HeartbeatSeconds).

If the state defines a TimeoutSeconds and the callback doesn’t arrive in time, Step Functions fails the state with a States.Timeout error. Similarly, if a heartbeat is required and not received, the state fails with States.HeartbeatTimeout.

Here’s a simple example: a workflow that processes an order, pauses for a manager’s approval, then continues. The approval step is a Lambda function that sends the token to a human via email. The manager clicks “Approve� in a custom app, which calls SendTaskSuccess with the token and perhaps some notes. The workflow then resumes and sends the order to the warehouse.

Why Use Callbacks Instead of Polling or Synchronous Calls?

Before callbacks, you might have used a polling loop: a Lambda function checks a database every minute until a status changes. That wastes compute time and adds complexity. Or you might have used a synchronous HTTP call that blocks until the external service responds—which often isn’t possible if the process takes hours or if the client disconnects.

Callbacks give you several benefits:

  • No idle compute: The state machine doesn’t run any code while waiting; it simply pauses.
  • Clean state: The execution history records exactly where it paused and what happened.
  • Built-in timeout handling: You can set timeouts and heartbeats to detect stuck processes.
  • Integration with any system: As long as the external system can make an AWS API call (using SDK, CLI, or HTTP via API Gateway), it can resume the workflow.

This pattern is especially useful for human-in-the-loop workflows, where a person must review or approve something. The workflow waits indefinitely (or for a defined timeout) without consuming resources.

Common Use Cases and Examples

Webhook callbacks are used in a wide variety of scenarios:

  • Human approval: An expense report triggers a workflow that pauses until a manager approves or rejects it via a web form.
  • Payment processing: A workflow creates a payment intent, then waits for the payment gateway to confirm success or failure asynchronously.
  • Long-running batch jobs: A workflow starts an EMR or AWS Batch job, then waits for a completion callback from the job’s notification system.
  • Third-party integrations: An external SaaS sends a webhook to your API Gateway, which then calls SendTaskSuccess to resume the workflow.
  • Manual data validation: A data pipeline pauses for a human to review a sample of records before final processing.

For example, consider a document approval workflow. The first state calls a Lambda that generates a shareable link and sends an email with the token. The workflow pauses. When the recipient clicks “Approve,� an API Gateway endpoint receives the request, extracts the token, and calls SendTaskSuccess with the approval details. The workflow then moves to the next state, perhaps sending a notification to the requester.

Setting Up a Callback Task: Step-by-Step

To configure a callback in your state machine definition (Amazon States Language):

  1. Define a task state (e.g., "Type": "Task") with a resource that supports callbacks—Lambda, Activity, or a service integration like ECS or SQS.
  2. Add "WaitForCallback": true to the state’s Parameters or as a top-level field (for some integrations).
  3. Set TimeoutSeconds to the maximum time you’re willing to wait (e.g., 86400 for a day).
  4. If you want to detect dead tasks, set HeartbeatSeconds (e.g., 600) and have the external system call SendTaskHeartbeat periodically.
  5. In your task code, extract the token from the event (for Lambda) or from the activity task.
  6. Pass the token to the external system—via email, HTTP response, or storing it in a database.
  7. When the external work completes, call the appropriate SendTask* API with the token.

Here’s a minimal JSON snippet for a Lambda-backed callback state:

{
  "Type": "Task",
  "Resource": "arn:aws:lambda:us-east-1:123456789012:function:send-approval",
  "Parameters": {
    "taskToken.$": "$$.Task.Token"
  },
  "WaitForCallback": true,
  "TimeoutSeconds": 86400,
  "HeartbeatSeconds": 3600,
  "Next": "ProcessApproval"
}

Note: The exact location of WaitForCallback depends on the service integration. For Lambda, it’s in the Parameters; for Activity, it’s a top-level field. Always check the current AWS documentation for the service you’re using.

Common Pitfalls and How to Avoid Them

Callbacks are powerful but have a few traps:

  • Token loss: If the external system loses the token, the workflow will never resume. Store the token securely, and consider logging it (but be careful with sensitive data).
  • Timeout too short: If you set a timeout that’s too tight, the workflow will fail even if the external process is still working correctly. Choose a realistic maximum.
  • Missing heartbeat: If you require heartbeats but the external system doesn’t send them, the state will fail. Make sure the system is designed to send heartbeats at the right interval.
  • Duplicate callbacks: If the external system calls SendTaskSuccess twice, the second call will fail with a TaskTimedOut or InvalidToken error. Make your external system idempotent.
  • Token in logs: The token is sensitive—it can resume or fail the workflow. Avoid logging it in plain text; use AWS Secrets Manager or parameter store if needed.

Another common misconception is that callbacks are only for Lambda. In fact, you can use them with any task that supports the pattern, including ECS tasks, SQS, and even custom activities. Activities are particularly useful for integrating with legacy systems that can’t call AWS APIs directly—they poll for work and then call back with the token.

Costs and Performance Considerations

Step Functions pricing is based on the number of state transitions and the duration of execution. A callback state that waits for days will incur costs for the time it’s waiting, but the rate is very low compared to running a compute resource. As of the current pricing model, you pay per state transition and per GB-hour of execution memory, but waiting states consume minimal resources.

For long waits, the cost is negligible compared to, say, a running EC2 instance. However, you should still design for efficiency: keep the number of transitions low and use timeouts to avoid infinite waits. Also, consider using a separate state machine for the external process if it’s very long-running, and have the callback resume the main workflow.

Performance-wise, callbacks add minimal latency—the resume is near-instant once the API call is made. The main bottleneck is the external system’s own speed.

Alternatives to Webhook Callbacks

Callbacks aren’t the only way to handle long-running workflows in Step Functions:

  • Polling: A loop that checks a database or API until a condition is met. Simpler but wastes compute and adds latency.
  • Synchronous Express Workflows: These run for up to 5 minutes and are cheaper for short tasks, but they can’t wait for external callbacks.
  • EventBridge Integration: You can have a workflow publish an event and then wait for a response event using a state that listens for a specific event pattern. This is more event-driven but requires more setup.
  • Step Functions StartExecution with a callback: You can start a child workflow and wait for it to complete using the Run a Job pattern with ServiceIntegrationPattern set to SYNC, but that’s for synchronous calls, not external callbacks.

For most cases, callbacks are the cleanest and most direct way to integrate external systems. They’re a core feature of Step Functions and are well-supported across AWS services.

Frequently Asked Questions

Can I use webhook callbacks with API Gateway?

Yes, you can. API Gateway can receive an HTTP request from an external system, extract the token, and call SendTaskSuccess via a Lambda function or direct AWS SDK call. This effectively turns an HTTP webhook into a Step Functions callback.

What happens if the external system never calls back?

The state will wait until the TimeoutSeconds expires, then fail with a States.Timeout error. If you don’t set a timeout, it will wait indefinitely, which can be risky. Always set a timeout and handle the failure in your state machine.

Can I send a callback from inside a Lambda function?

Yes, a Lambda function can call SendTaskSuccess or SendTaskFailure using the AWS SDK. This is common when the Lambda itself performs the external work or triggers another service that will eventually call back.

Is the task token reusable?

No, each token is unique to a specific execution and state. Once you call SendTaskSuccess or SendTaskFailure, the token becomes invalid. If you need to retry, you must design your workflow to handle that (e.g., by starting a new execution).

Can I use callbacks with Step Functions Express Workflows?

No, Express Workflows are designed for short, synchronous executions and do not support the wait-for-callback pattern. Use Standard Workflows for long-running processes with callbacks.

How do I test a callback state?

You can test by manually invoking the SendTaskSuccess API with a token you obtain from the execution. During development, you can temporarily set a short timeout and use the Step Functions console to see the token in the execution input/output.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.