AWS Lambda Durable Execution SDK for .NET
July 1, 2026 · View on GitHub
Preview.
Amazon.Lambda.DurableExecutionis in active development (0.x). Public APIs may change before 1.0.
Amazon.Lambda.DurableExecution is the .NET SDK for building resilient, long-running AWS Lambda functions that automatically checkpoint progress and resume after failures. Workflows can run for up to one year, with charges only for active compute time.
Key Features
- Automatic checkpointing — progress is saved after each step; failures resume from the last checkpoint.
- Cost-effective waits — suspend execution for minutes, hours, or days without compute charges.
- Configurable retries — built-in retry strategies with exponential backoff and jitter.
- Replay safety — functions deterministically resume from checkpoints after interruptions.
- Type safety — full generic type support for step results.
- AOT-friendly — pluggable
ILambdaSerializerso you can registerSourceGeneratorLambdaJsonSerializer<TContext>for trimmed / Native AOT functions.
How It Works
Your handler delegates to DurableFunction.WrapAsync, which gives your workflow function an IDurableContext. The context is your interface to durable operations:
ctx.StepAsync— run code and checkpoint the result. (docs)ctx.WaitAsync— suspend execution without compute charges. (docs)ctx.WaitForConditionAsync— poll a check function until a condition is met, suspending between polls. (docs)ctx.CreateCallbackAsync/ctx.WaitForCallbackAsync— wait for external events (approvals, webhooks). (docs)ctx.RunInChildContextAsync— run an isolated child context with its own checkpoint log. (docs)ctx.ParallelAsync— run independent branches concurrently and aggregate their results. (docs)- Every user
Funcreceives aCancellationTokenlinking the caller's token with the SDK's workflow-shutdown signal. (docs)
Quick Start
Installation
dotnet add package Amazon.Lambda.DurableExecution
Your first durable function
Programming model: durable functions support both the executable programming model (shown below) and the class-library programming model on the managed
dotnet10runtime. See the class-library variant below.
A complete order-processing workflow with two steps and a wait, deployed as an executable assembly on the dotnet10 runtime. Main builds a LambdaBootstrap with your handler and an ILambdaSerializer, and DurableFunction.WrapAsync uses that serializer to checkpoint step inputs and outputs.
using Amazon.Lambda.Core;
using Amazon.Lambda.DurableExecution;
using Amazon.Lambda.RuntimeSupport;
using Amazon.Lambda.Serialization.SystemTextJson;
namespace OrderProcessor;
public class OrderProcessor
{
public static async Task Main()
{
var handler = new OrderProcessor();
var serializer = new DefaultLambdaJsonSerializer();
using var wrapper = HandlerWrapper.GetHandlerWrapper<DurableExecutionInvocationInput, DurableExecutionInvocationOutput>(
handler.Handler, serializer);
using var bootstrap = new LambdaBootstrap(wrapper);
await bootstrap.RunAsync();
}
public Task<DurableExecutionInvocationOutput> Handler(
DurableExecutionInvocationInput input, ILambdaContext context)
=> 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);
For AOT or trim-friendly serialization, swap DefaultLambdaJsonSerializer for SourceGeneratorLambdaJsonSerializer<TContext> and register your JsonSerializerContext.
Class-library programming model
On the managed dotnet10 runtime you can skip the Main/LambdaBootstrap loop entirely and deploy a plain class-library handler — the same model used by non-durable Lambda functions. Declare the serializer with an assembly attribute and deploy with the Assembly::Namespace.Type::Method handler string (e.g. OrderProcessor::OrderProcessor.OrderProcessor::Handler):
using Amazon.Lambda.Core;
using Amazon.Lambda.DurableExecution;
using Amazon.Lambda.Serialization.SystemTextJson;
[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]
namespace OrderProcessor;
public class OrderProcessor
{
public Task<DurableExecutionInvocationOutput> Handler(
DurableExecutionInvocationInput input, ILambdaContext context)
=> DurableFunction.WrapAsync<Order, OrderResult>(Workflow, input, context);
private async Task<OrderResult> Workflow(Order order, IDurableContext ctx)
{
// ...same workflow body as above...
}
}
The project is a normal Lambda class library; the managed runtime supplies the bootstrap loop and invokes Handler directly.
Using Lambda Annotations
If you use Amazon.Lambda.Annotations, you can skip the handler/WrapAsync boilerplate. Annotate your workflow method with both [LambdaFunction] and [DurableExecution] — the source generator emits the handler wrapper that calls DurableFunction.WrapAsync, and adds the DurableConfig block and checkpoint-API IAM permissions to the generated serverless.template.
using Amazon.Lambda.Annotations;
using Amazon.Lambda.DurableExecution;
public class OrderProcessor
{
[LambdaFunction]
[DurableExecution(executionTimeout: 300, RetentionPeriodInDays = 7)]
public async Task<OrderResult> Workflow(Order order, IDurableContext ctx)
{
var reservation = await ctx.StepAsync(
async (_, ct) => await InventoryService.ReserveAsync(order.Items, ct),
name: "reserve-inventory");
// ... remaining steps ...
return new OrderResult(order.Id, /* ... */ "tracking");
}
}
Works with both the executable and class-library programming models — set [assembly: LambdaGlobalProperties(GenerateMain = true)] for the executable model, or omit it for a class library (the generated serverless.template Handler adapts to each). The generator validates the (TInput, IDurableContext) -> Task/Task<TOutput> signature and Zip packaging, and reports a diagnostic otherwise.
Documentation
Core operations
- Steps — execute code with automatic checkpointing, retry strategies, and at-least/at-most-once semantics.
- Wait — pause execution without compute charges.
- Wait For Condition — poll until a condition is met, suspending between polls with a configurable wait strategy.
- Callbacks — wait for external systems to respond.
- Child Contexts — group related operations into isolated, checkpointed units.
- Parallel — fan out independent branches concurrently with configurable concurrency and completion policies.
Examples
End-to-end test functions (each paired with an integration test) live under Libraries/test/Amazon.Lambda.DurableExecution.IntegrationTests/TestFunctions/.
Related SDKs
- aws-durable-execution-sdk-java — Java SDK
- aws-durable-execution-sdk-js — JavaScript / TypeScript SDK
- aws-durable-execution-sdk-python — Python SDK