AWS  

Building Durable .NET Workflows with AWS Lambda Durable Execution

Modern applications rarely consist of one short-running operation. An order may need inventory validation, payment processing, shipment creation, and notification. An AI workflow may call several models, wait for human approval, and continue hours later.

Traditionally, developers solve these problems with queues, databases, custom state machines, retry logic, or workflow services such as AWS Step Functions. AWS Lambda Durable Execution introduces another approach: keep the workflow logic in application code while Lambda manages checkpoints, replay, retries, and suspension.

For C# developers, this becomes particularly interesting with the general availability of the AWS Lambda Durable Execution SDK for .NET. AWS announced the .NET SDK as generally available on July 23, 2026. It provides an idiomatic C# programming model for building resilient, long-running Lambda workflows.

What Is AWS Lambda Durable Execution?

A normal Lambda invocation has a limited execution lifetime. If the function fails halfway through a multi-step process, the application has to determine what was already completed and what needs to run again.

Durable execution changes that model.

A durable Lambda function uses checkpoints and replay. Each durable operation records progress. If the execution is interrupted, Lambda can invoke the function again and replay the workflow while using previously stored results for completed operations.

Conceptually, consider this workflow:

Receive Order
     |
     v
Validate Order
     |
     v
Reserve Inventory
     |
     v
Process Payment
     |
     v
Wait for Warehouse
     |
     v
Create Shipment

If the function fails after payment has completed, the workflow does not have to blindly start from the beginning. The completed durable operations can be recovered from checkpoints.

A durable execution can span multiple Lambda invocations and can run for up to one year, while an individual Lambda invocation still has its normal execution limit.

Why Durable Execution Matters for .NET Developers

The important difference is not simply that Lambda can run longer.

The real benefit is that workflow state becomes part of the execution model.

With a traditional Lambda implementation, developers may need to build:

  • A persistence mechanism for workflow state

  • Retry handling

  • Recovery logic

  • Status tracking

  • Polling mechanisms

  • Coordination between Lambda functions

  • Logic to prevent already-completed work from running again

The .NET durable execution SDK provides these capabilities through a programming model based around IDurableContext and operations such as StepAsync, WaitAsync, callbacks, parallel execution, and durable invocation.

This allows the workflow to remain readable as ordinary C# code.

Installing the .NET Durable Execution SDK

The SDK is distributed as the Amazon.Lambda.DurableExecution NuGet package.

Create a Lambda project and add the package:

dotnet add package Amazon.Lambda.DurableExecution

AWS's current SDK implementation supports both executable and class-library programming models. The class-library model can be used with the managed dotnet10 Lambda runtime, while the executable model explicitly builds the Lambda bootstrap.

For most developers starting a new .NET Lambda application, the class-library approach is straightforward.

Building a Durable Order Workflow

Consider an order-processing workflow with four operations:

  1. Reserve inventory.

  2. Process payment.

  3. Wait for warehouse processing.

  4. Create the shipment.

A simplified implementation looks like this:

using Amazon.Lambda.Core;
using Amazon.Lambda.DurableExecution;
using Amazon.Lambda.Serialization.SystemTextJson;

[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]

namespace OrderProcessor;

public class Function
{
    public Task<DurableExecutionInvocationOutput> Handler(
        DurableExecutionInvocationInput input,
        ILambdaContext context)
    {
        return DurableFunction.WrapAsync<Order, OrderResult>(
            Workflow,
            input,
            context);
    }

    private async Task<OrderResult> Workflow(
        Order order,
        IDurableContext ctx)
    {
        var reservation = await ctx.StepAsync(
            async (_, ct) =>
                await InventoryService.ReserveAsync(order.Items, ct),
            name: "reserve-inventory");

        var payment = await ctx.StepAsync(
            async (_, ct) =>
                await PaymentService.ChargeAsync(
                    order.PaymentMethod,
                    order.Total,
                    ct),
            name: "process-payment");

        await ctx.WaitAsync(
            TimeSpan.FromHours(2),
            name: "warehouse-processing");

        var shipment = await ctx.StepAsync(
            async (_, ct) =>
                await ShippingService.ShipAsync(
                    reservation,
                    order.Address,
                    ct),
            name: "confirm-shipment");

        return new OrderResult(
            order.Id,
            shipment.TrackingNumber);
    }
}

public record Order(
    string Id,
    IReadOnlyList<OrderItem> Items,
    PaymentMethod PaymentMethod,
    decimal Total,
    Address Address);

public record OrderResult(
    string OrderId,
    string TrackingNumber);

The important part is the distinction between ordinary code and durable operations.

StepAsync wraps work that should be checkpointed. AWS's .NET SDK documentation shows this pattern for operations such as inventory reservation and payment processing. WaitAsync allows the execution to suspend without continuing to consume compute while it waits.

Understanding Checkpoint and Replay

Suppose reserve-inventory succeeds and process-payment also succeeds.

The execution then reaches:

await ctx.WaitAsync(
    TimeSpan.FromHours(2),
    name: "warehouse-processing");

The durable execution can suspend at this point.

When the workflow resumes, the application code is replayed. However, previously completed durable operations use their checkpointed results rather than performing the same business operation again.

That distinction is critical.

A developer should not assume that the Lambda handler itself runs only once. A durable execution can contain multiple invocations and replays.

The Most Important Rule: Make Workflow Code Deterministic

Replay introduces an important programming constraint.

Code that participates in the workflow must produce consistent results when replayed. Operations that can return different results should generally be placed inside an appropriate durable operation.

For example, avoid relying on an uncontrolled random value in orchestration logic:

var requestId = Guid.NewGuid().ToString();

If that value influences workflow state, replay can produce a different value.

Instead, generate values that need to survive replay inside a checkpointed operation:

var requestId = await ctx.StepAsync(
    async (_, ct) =>
    {
        await Task.CompletedTask;
        return Guid.NewGuid().ToString();
    },
    name: "generate-request-id");

The broader principle is simple: external side effects and nondeterministic work should not accidentally become part of replay-sensitive orchestration code.

This is one of the biggest differences between writing an ordinary Lambda handler and writing a durable workflow.

Handling Long Waits

One of the strongest use cases for durable execution is waiting.

For example:

await ctx.WaitAsync(
    TimeSpan.FromHours(24),
    name: "customer-confirmation-window");

A normal function should not remain alive for 24 hours simply waiting for an event.

Durable execution can suspend the workflow and resume it later. AWS states that waits suspend execution without consuming compute charges, making the model suitable for workflows that may wait minutes, hours, or days.

Typical examples include:

  • Customer approval

  • Payment confirmation

  • External API completion

  • Document processing

  • Human-in-the-loop AI workflows

  • Scheduled follow-up operations

For events rather than fixed-duration waits, the SDK also provides callback and condition-based operations.

Durable Execution vs AWS Step Functions

Durable execution does not make Step Functions obsolete. The two services solve related but different architectural problems.

AreaLambda Durable ExecutionAWS Step Functions
Workflow definitionC# and application codeState machine
Primary abstractionDurable Lambda functionWorkflow orchestration service
State managementCheckpoints and replayManaged workflow state
Developer experienceCode-centricWorkflow-centric
Long waitsSupportedSupported
AWS service integrationsPrimarily through application codeExtensive native integrations
Visual workflowNot the primary modelStrong visual workflow model
Best fitApplication-level workflowsCross-service orchestration

AWS describes durable functions as optimized for application development within Lambda, while Step Functions is designed for workflow orchestration across AWS services.

A practical architecture can also use both. A higher-level Step Functions workflow can coordinate services while a durable Lambda handles complex application logic inside one part of the process.

Production Configuration Considerations

Durable execution has configuration that is separate from the normal Lambda invocation timeout.

The durable execution configuration controls the total execution lifetime and execution-history retention. AWS documents ExecutionTimeout and RetentionPeriodInDays as part of the durable function configuration.

There is an important deployment consideration: durable execution must be enabled when the function is created; AWS currently does not allow enabling it on an existing Lambda function.

For production deployments, use Infrastructure as Code so the durable configuration, IAM permissions, runtime, and deployment settings are version controlled.

AWS also requires durable functions to use qualified function ARNs, such as published versions or aliases, for deterministic production invocation.

IAM Permissions

The Lambda execution role needs permissions for durable checkpoint operations.

AWS identifies the relevant permissions as:

lambda:CheckpointDurableExecution
lambda:GetDurableExecutionState

The AWS-managed AWSLambdaBasicDurableExecutionRolePolicy includes these permissions.

Do not treat these permissions as optional deployment details. A workflow can be correctly implemented in C# and still fail operationally if the Lambda execution role cannot persist or retrieve durable execution state.

Retries and Idempotency

Durable execution provides retry capabilities for durable steps, including configurable retry strategies.

However, retries do not remove the need for idempotent business operations.

Consider:

await ctx.StepAsync(
    async (_, ct) =>
    {
        await PaymentService.ChargeAsync(order.PaymentMethod, ct);
        return true;
    },
    name: "charge-payment");

A payment operation is a side effect. In production, the payment provider should support an idempotency key so that a retry cannot accidentally create multiple charges.

The durable workflow gives you reliable execution semantics; your external systems still need appropriate business-level idempotency.

Common Mistakes

Putting external calls outside durable steps

If an external API call is part of a workflow step, keep the operation inside the durable operation rather than making it an uncontrolled side effect in replay-sensitive orchestration code.

Assuming the handler executes only once

Durable execution can involve multiple Lambda invocations and replay. Design workflow code with this lifecycle in mind.

Using unstable values in orchestration logic

Random values, current timestamps, and changing external state can produce inconsistent behavior during replay when they are not handled correctly.

Treating retries as a replacement for idempotency

Retries can cause an operation to be attempted again. Payment, email, order creation, and other external side effects should have their own idempotency strategy.

Deploying mutable production code

Long-running workflows need deterministic code behavior. Use published Lambda versions or aliases rather than relying on mutable $LATEST for production durable executions.

Troubleshooting Checklist

When a durable workflow does not behave as expected, check these areas first:

  1. Is durable execution enabled on the Lambda function?

  2. Does the IAM role include checkpoint permissions?

  3. Are durable operations used around important side effects?

  4. Could replay produce different values?

  5. Are external operations idempotent?

  6. Is the production function invoked through a qualified version or alias?

  7. Are execution timeout and history retention configured appropriately?

  8. Are CloudWatch logs and durable execution status being monitored?

AWS also provides APIs for inspecting durable executions, including status, input, results, errors, and execution metadata.

When Should You Use Lambda Durable Execution?

Durable execution is a strong fit when the application has workflow logic that naturally reads as sequential application code.

Good candidates include:

  • Multi-step order processing

  • Payment workflows

  • Human approval processes

  • Long-running document processing

  • AI agent orchestration

  • Reliable Lambda-to-Lambda workflows

  • Workflows that need explicit retries and recovery

It is less compelling when the problem is simply a single short-lived Lambda operation or when the primary requirement is extensive cross-service orchestration with a visual state-machine model.

The key architectural question is not "Can this run on Lambda?" but rather:

Does this application need durable workflow state while keeping the workflow logic in C# code?

If the answer is yes, Lambda Durable Execution is worth evaluating.

Best Practices

For production .NET workflows, keep these principles in mind:

  1. Use durable operations for meaningful units of work.

  2. Keep orchestration code deterministic.

  3. Design external side effects to be idempotent.

  4. Use published Lambda versions or aliases.

  5. Keep checkpoint payloads reasonably sized.

  6. Use explicit step names that remain stable across deployments.

  7. Configure retries according to the failure characteristics of each operation.

  8. Use Infrastructure as Code for durable function configuration.

  9. Monitor long-running executions rather than relying only on standard invocation metrics.

  10. Choose Step Functions when visual, cross-service orchestration is the better abstraction.

Conclusion

AWS Lambda Durable Execution changes how .NET developers can approach long-running serverless workflows.

Instead of building a separate state-management layer around Lambda, developers can express workflow logic using C# and durable operations such as StepAsync and WaitAsync. Lambda then manages checkpointing, replay, and execution recovery.

The newly generally available .NET SDK makes this model particularly relevant to C# teams. The strongest use cases are not ordinary Lambda functions, but multi-step workflows where failures, retries, waits, and recovery are part of the business process.

The important mindset shift is to stop thinking of a durable Lambda as one function invocation. Think of it as a long-lived workflow whose execution may span multiple Lambda invocations while preserving progress.

That distinction is what makes durable execution useful for production .NET applications.

Frequently Asked Questions

Can a durable Lambda run for days?

Yes. The durable execution lifecycle can span multiple Lambda invocations and can have a total execution timeout of up to one year, while individual Lambda invocations retain their normal execution limits.

Does waiting consume Lambda compute?

No. Durable wait operations suspend execution rather than keeping the Lambda invocation running during the wait.

Is durable execution a replacement for Step Functions?

Not universally. Durable functions are code-centric and suited to application logic inside Lambda. Step Functions remains a strong choice for broader workflow orchestration and native AWS service integration.

Does the .NET SDK support local testing?

Yes. AWS's .NET SDK includes a local testing emulator intended to help developers build and debug durable functions before deploying them to AWS.

Which NuGet package is used?

The AWS .NET durable execution package is Amazon.Lambda.DurableExecution.