Durable Functions in Lambda
Source: Dev.to
What are Durable Functions?
Durable Functions let you build multi‑step applications and workflows directly in AWS Lambda.
You can pause your app and continue later based on callbacks, all while staying on the proven Lambda platform. This capability was announced at Reinvent 2025.
How Does it Work?
Durable Functions manage state, checkpoints, and retries for you. Each step in a workflow is treated as a separate durable step, allowing the system to:
- Skip already‑completed steps on retries.
- Handle external API calls with built‑in retries and exponential back‑off.
- Wait for asynchronous callbacks (e.g., from an ERP system) without incurring idle compute costs.
- Pause for human approval before proceeding.
Use Cases for Durable Functions
| Scenario | Traditional Approach | Durable Functions Advantage |
|---|---|---|
| Order processing – reserve inventory → process payment → create shipment | Custom code needed to track which steps succeeded; manual idempotency handling. | Automatic checkpointing prevents duplicate reservations; retries are handled transparently. |
| External API calls (e.g., payment gateway) | Implement retries, back‑off, and error handling manually. | Native retry policies configurable per step. |
| Async ERP integration | Polling or long‑running Lambda invocations waste resources. | Wait for a callback without paying for idle time. |
| Human‑in‑the‑loop | Must build custom pause/resume logic. | Built‑in waiting for human approval before continuing. |
How to Create Durable Functions
Durable Functions are defined using Python decorators:
Sample Code
from aws_durable_execution_sdk_python import (
DurableContext,
durable_execution,
durable_step,
)
from aws_durable_execution_sdk_python.config import Duration
@durable_step
def validate_order(step_context, order_id):
step_context.logger.info(f"Validating order {order_id}")
return {"orderId": order_id, "status": "validated"}
@durable_step
def process_payment(step_context, order_id):
step_context.logger.info(f"Processing payment for order {order_id}")
return {"orderId": order_id, "status": "paid", "amount": 99.99}
@durable_step
def confirm_order(step_context, order_id):
step_context.logger.info(f"Confirming order {order_id}")
return {"orderId": order_id, "status": "confirmed"}
@durable_execution
def lambda_handler(event, context: DurableContext):
order_id = event['orderId']
# Step 1: Validate order
validation_result = context.step(validate_order(order_id))
# Step 2: Process payment
payment_result = context.step(process_payment(order_id))
# Simulate external confirmation wait
context.wait(Duration.from_seconds(10))
# Step 3: Confirm order
confirmation_result = context.step(confirm_order(order_id))
return {
"orderId": order_id,
"status": "completed",
"steps": [validation_result, payment_result, confirmation_result]
}
After deployment, you can view executions in the Durable Executions tab of the Lambda console. The console shows:
- Step inputs, outputs, and logs.
- Event history, including any waits or callbacks.
The UI resembles the Step Functions console, but the underlying modeling and observability differ.
Comparison with Step Functions
| Attribute | Durable Functions | Step Functions |
|---|---|---|
| Development model | Imperative (code‑first) | Declarative (state‑machine) |
| Best for | Orchestrating Lambda‑centric business logic | Orchestrating across many AWS services |
| Observability | CloudWatch logs | Visual graphs & execution history |
When to Use Which
Prefer Lambda Durable Functions when:
- The workflow is primarily Lambda‑based business logic.
- Your team favors a code‑first approach with strong unit‑testability.
- You need long‑running, pause/resume behavior without building a full state machine.
- Visual workflow designers or extensive service integrations are not required.
Prefer Step Functions when:
- The workflow orchestrates many AWS services or external systems.
- Visual observability and low‑code configuration are important.
- You have complex branching, human‑in‑the‑loop steps, or high‑fanout orchestration.
- You want a clear separation between orchestration (state machine) and implementation (Lambdas/other services).