What if -
You could build multi-step applications and workflows - directly in Lambda?
Pause your app and continue based on callbacks?
All this, with the tried and tested AWS Lambda platform?
All this and more are possible with the new Durable Function Lambda announced during Reinvent 2025.
What are Durable Functions?
Lambda Durable Functions let you build resilient multi-step applications and workflows that can run up to a year, while preserving progress state across interruptions. Each run is called a Durable Execution. Each time checkpoints record the state so system can automatically recover from failures by replaying the execution - starting from the beginning but skipping any work that has already been completed.
How Does it Work?
Behind the scenes, durable functions use Lambda functions that use a checkpoint-and-replay mechanism. This tracks and supports long-running executions. When a durable function resumes from a wait state (suspension) or does a retry, your code runs from the beginning but checks what has already been completed by using checkpoints. Then it skips the steps that has been completed. It will just reuse the results of the completed checkpoints. This replay mechanism preserves the consistency.
Use Cases for Durable Functions
Many applications that you might have used, such as services like Step Functions or Orchestrated microservices, could be done using Lambda Durable Function.
For example, an order processing system might have these steps: reserve inventory, process payment, and create shipment.
Previously, if you reserve your inventory and then fail in one of the next steps, on potential retries you had to make sure to not reserve the item again, this required custom code to be written or other scaffolding. Now in Durable functions, these will be three separate steps. On retry, Lambda sees the checkpoint for reserving, and does not reserve again, automatically without you doing anything.
Payment processing could be an external api that requires you to implement retries, exponential backoff etc according to the API contract. These are handled natively by Durable Functions and are just parameters for the step.
Maybe the reserving happens in an external ERP system, and it is async. Earlier, your lambda or custom code has to wait (expensive waste) or poll status. Now, with durable functions, it can just wait and use a callback from the ERP system without spending any money for the wait.
Maybe you need a human to approve before creating the shipment. Durable functions can wait for human intervention before proceeding.
How to create Durable Functions
We create Durable Functions just like any Lambda, using the Lambda console or other IaC. Currently, it is available for NodeJS and Python, and in select regions only. (Ohio only as of now)
We use decorators in Python to designate parts of code as Durable Steps and Durable Execution.
Durable Step
Executes business logic with automatic checkpointing and retry. Use steps for operations that call external services, perform calculations, or execute any logic that should be checkpointed. The SDK creates a checkpoint before and after the step, storing the result for replay.
Durable Execution
How the Steps are run, where waits will happen or callbacks.
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))
# Wait for 10 seconds to simulate external confirmation
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]
}
Once you run the Durable Function, you can see them in the new Durable Executions tab in Lambda console. Durable operations show the steps in the Durable Execution. It shows all the executions of this Durable Function.
You can go to Durable Operations. Here you can see the inputs, outputs, logs, etc. from the individual steps.
Event History shows the events during the Durable Execution. If you had a wait, etc., it will show here.
If these Durable Function screens are looking like the Step Function screens, you are not mistaken. They overlap in use cases, but they differ in how you model workflows, how observable they are, and where they work best.
| Attribute | Durable Fn | Step Fn |
|---|---|---|
| Development | Imperative | Declarative |
| Best For | Orchestrate with one Function | Orchestrate among AWS services |
| Observability | CloudWatch | Visual Graphs |
Here is a general guideline on when to use what
Prefer Lambda Durable Functions when:
Workflow is primarily Lambda-based business logic.
Team wants a code-first model and strong unit-testability.
You need long-running, pause/resume behavior without building a full state machine.
You do not require a visual workflow designer or many direct service integrations.
Prefer Step Functions when:
Workflow orchestrates many AWS services and external systems.
Visual observability and low-code configuration are important to the team.
You have complex branching, human-in-the-loop, or very high-fanout orchestration.
You want a clear separation between orchestration (state machine) and implementation (Lambdas/other services).



Top comments (0)