Skip to content

DurableFunction

Source: src/AWS/Lambda/DurableFunction.ts

An AWS Lambda Durable Function — a code-first, replay-based orchestrator that IS a durable Lambda Function. AWS.Lambda.DurableFunction is a wrapper of Function: it owns the underlying Lambda function, configures its DurableConfig at CreateFunction (durability is a create-time property — a DurableFunction is always durable), registers the durable-execution listener on the owned entrypoint, self-binds the checkpoint-protocol IAM (lambda:CheckpointDurableExecution, lambda:GetDurableExecutionState) onto the execution role, and vendors the open-source @aws/durable-execution-sdk-js into the artifact (install it in your project: npm i @aws/durable-execution-sdk-js).

Executions progress by checkpoint + replay: a Durable.sleep or Durable.waitForCallback suspends the execution with zero compute billed until Lambda re-invokes the same function version to resume, and completed Durable.steps replay from the checkpoint log without re-executing.

Every invocation of a durable function arrives as the durable-execution envelope, so a DurableFunction has no HTTP surface (url is disabled) — it does one thing: run durable orchestrations. Reusing a logical id between a plain Function and a DurableFunction replaces the physical function (DurableConfig cannot be flipped in place).

Class form with steps and a durable sleep

export class OrderFlow extends AWS.Lambda.DurableFunction<OrderFlow>()(
"OrderFlow",
{
main: import.meta.url,
executionTimeout: "1 hour",
retentionPeriod: "7 days",
},
Effect.gen(function* () {
// init: resolve typed binding clients (IAM lands on this function's role)
const putItem = yield* AWS.DynamoDB.PutItem(table);
return Effect.fn(function* (input: { orderId: string }) {
const reserved = yield* AWS.Lambda.Durable.step(
"reserve",
putItem({ Item: { pk: { S: input.orderId } } }).pipe(Effect.orDie),
{ retry: { limit: 3, delay: "5 seconds" } },
);
yield* AWS.Lambda.Durable.sleep("cooldown", "10 minutes");
return { orderId: input.orderId, reserved };
});
}),
) {}

Tag + default export (entrypoint form)

// order-flow.ts — `main` points at this module
export class OrderFlow extends AWS.Lambda.DurableFunction<OrderFlow>()(
"OrderFlow",
) {}
export default OrderFlow.make(
{ main: import.meta.url, executionTimeout: "1 hour" },
Effect.gen(function* () {
return Effect.fn(function* (input: { orderId: string }) {
return yield* AWS.Lambda.Durable.step("work", doWork(input));
});
}),
);

Inline effect form

const flow = yield* AWS.Lambda.DurableFunction(
"OrderFlow",
{ main: "./src/order-flow.ts" },
Effect.gen(function* () {
return Effect.fn(function* (input: { orderId: string }) {
return yield* AWS.Lambda.Durable.step("work", doWork(input));
});
}),
);

Starting an execution

const orders = yield* OrderFlow;
const ref = yield* orders.start({
name: "order-123", // idempotent start
params: { orderId: "123" },
});

Checking status

const execution = yield* orders.get(ref.executionArn!);
// execution.Status: "RUNNING" | "SUCCEEDED" | "FAILED" | ...
const approval = yield* AWS.Lambda.Durable.waitForCallback<{ ok: boolean }>(
"approve",
(callbackId) => storeCallbackId(callbackId),
{ timeout: "1 day" },
);