Durable Functions in Lambda

Published: (January 15, 2026 at 04:22 AM EST)
3 min read
Source: Dev.to

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

ScenarioTraditional ApproachDurable Functions Advantage
Order processing – reserve inventory → process payment → create shipmentCustom 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 integrationPolling or long‑running Lambda invocations waste resources.Wait for a callback without paying for idle time.
Human‑in‑the‑loopMust 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

AttributeDurable FunctionsStep Functions
Development modelImperative (code‑first)Declarative (state‑machine)
Best forOrchestrating Lambda‑centric business logicOrchestrating across many AWS services
ObservabilityCloudWatch logsVisual 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).
Back to Blog

Related posts

Read more »