Durable Execution SDK for .NET β Preview Now Available π
The AWS Lambda .NET team is excited to announce the preview of the AWS Lambda Durable Execution SDK for .NET (Amazon.Lambda.DurableExecution).
Durable Execution lets you build resilient, long-running Lambda functions that automatically checkpoint their progress and resume after failures. Workflows can run for up to one year, and you're only charged for active compute time β not for the time spent waiting.
Why Durable Execution?
Today, orchestrating multi-step workflows in Lambda often means stitching together Step Functions state machines, SQS queues, or DynamoDB-backed state, and writing your own logic to track progress and recover from failures. Durable Execution lets you express that same workflow as ordinary C# code β await your steps, your waits, and your callbacks β while the SDK handles checkpointing, retries, and replay-safe resumption for you.
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
ILambdaSerializer for trimmed / Native AOT functions.
For example, a multi-step order workflow with a built-in wait becomes:
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");
// Suspend for 2 hours with no compute charges, then resume.
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);
}
The first preview is available on NuGet:
π¦ Amazon.Lambda.DurableExecution 0.1.1-preview
dotnet add package Amazon.Lambda.DurableExecution --version 0.1.1-preview
Preview status. Amazon.Lambda.DurableExecution is in active development (0.x). Public APIs may change before 1.0.
Deployment. Durable functions deploy as a plain zip package on the managed dotnet10 runtime β Both the executable programming model (a Main that builds a LambdaBootstrap) and the class-library programming model (a plain Handler method, the same model used by non-durable functions) are supported.
Deploying a durable function (zip on the managed runtime)
The end-to-end integration tests build, deploy, and invoke durable functions exactly this way. See DurableFunctionDeployment.cs for the full lifecycle (IAM role β dotnet publish β zip β CreateFunction β invoke), and the TestFunctions/ folder for runnable example functions (each paired with a test).
1. Project file β choose either programming model.
Executable model β build an executable named bootstrap:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<OutputType>Exe</OutputType>
<AssemblyName>bootstrap</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.DurableExecution" Version="0.1.1-preview" />
<PackageReference Include="Amazon.Lambda.RuntimeSupport" Version="*" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="*" />
</ItemGroup>
</Project>
Class-library model β a normal Lambda class library (no OutputType, no RuntimeSupport reference); the managed runtime supplies the bootstrap loop:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AWSProjectType>Lambda</AWSProjectType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.DurableExecution" Version="0.1.1-preview" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="*" />
</ItemGroup>
</Project>
2. Handler β the executable model wires up LambdaBootstrap in Main; the class-library model declares the serializer with an assembly attribute and exposes a plain Handler.
Executable model:
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) { /* ... */ }
}
Class-library model:
[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]
namespace OrderProcessor;
public class Function
{
public Task<DurableExecutionInvocationOutput> Handler(
DurableExecutionInvocationInput input, ILambdaContext context)
=> DurableFunction.WrapAsync<Order, OrderResult>(Workflow, input, context);
private async Task<OrderResult> Workflow(Order order, IDurableContext ctx) { /* ... */ }
}
3. Publish and zip the package:
# Publish a framework-dependent Linux build (the dotnet:10 managed runtime supplies the runtime)
dotnet publish -c Release -r linux-x64 --self-contained false -o bin/publish
# Zip the publish output (no top-level folder)
cd bin/publish && zip -r ../function.zip . && cd -
4. Create the function as a zip package on the managed dotnet10 runtime, with a DurableConfig. The execution role needs both the basic execution policy and the durable execution policy:
arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy
await lambdaClient.CreateFunctionAsync(new CreateFunctionRequest
{
FunctionName = "my-durable-fn",
Runtime = "dotnet10",
// Executable model: "bootstrap".
// Class-library model: an Assembly::Namespace.Type::Method string,
// e.g. "OrderProcessor::OrderProcessor.Function::Handler".
Handler = "bootstrap",
Role = roleArn,
Code = new FunctionCode { ZipFile = new MemoryStream(File.ReadAllBytes("bin/function.zip")) },
Timeout = 30,
MemorySize = 256,
DurableConfig = new DurableConfig { ExecutionTimeout = 60 }
});
5. Invoke it with a DurableExecutionName, then track it via GetDurableExecution / GetDurableExecutionHistory:
await lambdaClient.InvokeAsync(new InvokeRequest
{
FunctionName = "my-durable-fn",
Qualifier = "$LATEST",
Payload = payload,
DurableExecutionName = $"order-{Guid.NewGuid():N}"
});
Core operations
Your handler delegates to DurableFunction.WrapAsync, which gives your workflow an IDurableContext β your interface to durable 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.
- Callbacks β wait for external systems (approvals, webhooks) to respond.
- Child Contexts β group related operations into isolated, checkpointed units.
π Learn more in the Durable Execution SDK README, which includes a complete getting-started walkthrough and full examples of both the executable and class-library programming models.
Related SDKs
Durable Execution is available across multiple languages:
What's still to come π§
This is an early preview and we're actively building. On the roadmap:
We want your feedback π
We cannot overstate how critical your feedback is during preview. Please try it out and let us know what works, what doesn't, and what you'd like to see before 1.0 β comment on this issue!
Durable Execution SDK for .NET β Preview Now Available π
The AWS Lambda .NET team is excited to announce the preview of the AWS Lambda Durable Execution SDK for .NET (
Amazon.Lambda.DurableExecution).Durable Execution lets you build resilient, long-running Lambda functions that automatically checkpoint their progress and resume after failures. Workflows can run for up to one year, and you're only charged for active compute time β not for the time spent waiting.
Why Durable Execution?
Today, orchestrating multi-step workflows in Lambda often means stitching together Step Functions state machines, SQS queues, or DynamoDB-backed state, and writing your own logic to track progress and recover from failures. Durable Execution lets you express that same workflow as ordinary C# code β
awaityour steps, your waits, and your callbacks β while the SDK handles checkpointing, retries, and replay-safe resumption for you.Key features
ILambdaSerializerfor trimmed / Native AOT functions.For example, a multi-step order workflow with a built-in wait becomes:
The first preview is available on NuGet:
π¦ Amazon.Lambda.DurableExecution
0.1.1-previewDeploying a durable function (zip on the managed runtime)
The end-to-end integration tests build, deploy, and invoke durable functions exactly this way. See
DurableFunctionDeployment.csfor the full lifecycle (IAM role βdotnet publishβ zip βCreateFunctionβ invoke), and theTestFunctions/folder for runnable example functions (each paired with a test).1. Project file β choose either programming model.
Executable model β build an executable named
bootstrap:Class-library model β a normal Lambda class library (no
OutputType, noRuntimeSupportreference); the managed runtime supplies the bootstrap loop:2. Handler β the executable model wires up
LambdaBootstrapinMain; the class-library model declares the serializer with an assembly attribute and exposes a plainHandler.Executable model:
Class-library model:
3. Publish and zip the package:
4. Create the function as a zip package on the managed
dotnet10runtime, with aDurableConfig. The execution role needs both the basic execution policy and the durable execution policy:arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRolearn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy5. Invoke it with a
DurableExecutionName, then track it viaGetDurableExecution/GetDurableExecutionHistory:Core operations
Your handler delegates to
DurableFunction.WrapAsync, which gives your workflow anIDurableContextβ your interface to durable operations:π Learn more in the Durable Execution SDK README, which includes a complete getting-started walkthrough and full examples of both the executable and class-library programming models.
Related SDKs
Durable Execution is available across multiple languages:
What's still to come π§
This is an early preview and we're actively building. On the roadmap:
ParallelAsyncβ fan out and run multiple durable branches concurrently.MapAsyncβ apply a durable operation across a collection of items.dotnet10runtime (no custom container image required).[DurableExecution]-style attributes.dotnet newtemplate to scaffold a durable function.We want your feedback π
We cannot overstate how critical your feedback is during preview. Please try it out and let us know what works, what doesn't, and what you'd like to see before
1.0β comment on this issue!