Skip to content

Instantly share code, notes, and snippets.

@ivanbarlog
Created January 27, 2026 13:50
Show Gist options
  • Select an option

  • Save ivanbarlog/7b108ac6b2782101a87bf115bc14d95e to your computer and use it in GitHub Desktop.

Select an option

Save ivanbarlog/7b108ac6b2782101a87bf115bc14d95e to your computer and use it in GitHub Desktop.
ASG Bratislava 01/2026 Durable Functions demo

Durable functions demo

Here is package.json used for this demo

{
  "name": "2026-01-asg-bratislava-demo",
  "type": "module",
  "private": true,
  "devDependencies": {
    "@types/aws-lambda": "^8.10.160",
    "@types/bun": "latest"
  },
  "peerDependencies": {
    "typescript": "^5"
  },
  "dependencies": {
    "@aws-sdk/client-lambda": "^3.975.0",
    "@aws/durable-execution-sdk-js": "^1.0.1",
    "aws-cdk": "^2.1103.0",
    "aws-cdk-lib": "^2.236.0",
    "constructs": "^10.4.5",
    "esbuild": "^0.27.2"
  },
  "scripts": {
    "cdk": "cdk --app \"bun app.ts\""
  }
}

Deployment

bun i

export AWS_PROFILE=yourprofile
export AWS_REGION=eu-central-1

bun run cdk bootstrap
bun run cdk deploy --require-approval never
import { App, Duration, Lazy, Stack } from "aws-cdk-lib";
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
import { Architecture, Runtime } from "aws-cdk-lib/aws-lambda";
import { NodejsFunction, SourceMapMode } from "aws-cdk-lib/aws-lambda-nodejs";
const stack = new Stack(new App(), "AsgDemo202601", {
env: {
account: "your account number",
region: "eu-central-1",
},
});
const lambda = new NodejsFunction(stack, "DurableFunction", {
entry: "durable.ts",
bundling: {
minify: false,
sourceMap: true,
sourceMapMode: SourceMapMode.EXTERNAL,
target: "es2022",
},
architecture: Architecture.ARM_64,
memorySize: 2048,
runtime: Runtime.NODEJS_24_X,
durableConfig: {
executionTimeout: Duration.minutes(1),
},
});
const callback = new NodejsFunction(stack, "DurableFunctionCallback", {
entry: "callback.ts",
bundling: {
minify: false,
sourceMap: true,
sourceMapMode: SourceMapMode.EXTERNAL,
target: "es2022",
// unfortunatelly at the time of coding this demo the bundled SDK did not recognized SendDurableExecutionCallbackSuccessCommand
bundleAwsSDK: true,
},
architecture: Architecture.ARM_64,
memorySize: 2048,
runtime: Runtime.NODEJS_24_X,
});
callback.grantInvoke(lambda);
callback.addToRolePolicy(
new PolicyStatement({
actions: ["lambda:SendDurableExecutionCallbackSuccess"],
effect: Effect.ALLOW,
// unfortunatelly there is no enough time on planet to try to solve "Circular dependency between resources" for demo code
resources: ["*"],
// otherwise we would use somehting like this:
// resources: lambda.resourceArnsForGrantInvoke,
}),
);
lambda.addEnvironment("CALLBACK_FUNCTION_ARN", callback.functionArn);
import {
LambdaClient,
SendDurableExecutionCallbackSuccessCommand,
} from "@aws-sdk/client-lambda";
const client = new LambdaClient();
interface Event {
readonly callbackId: string;
readonly request: {
readonly bid: number;
};
}
export const handler = async (event: Event) => {
if (event.request.bid > 100) {
await delay(1000);
const command = new SendDurableExecutionCallbackSuccessCommand({
CallbackId: event.callbackId,
Result: JSON.stringify({ accepted: true }),
});
await client.send(command);
} else {
await delay(2000);
const command = new SendDurableExecutionCallbackSuccessCommand({
CallbackId: event.callbackId,
Result: JSON.stringify({ accepted: false }),
});
await client.send(command);
}
};
async function delay(ms: number) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
import { InvokeCommand, LambdaClient } from "@aws-sdk/client-lambda";
import {
CallbackError,
withDurableExecution,
type DurableContext,
} from "@aws/durable-execution-sdk-js";
interface Request {
readonly bid: number;
}
interface Response {
readonly accepted: boolean;
}
const client = new LambdaClient();
export const handler = withDurableExecution<Request, Response>(
async (request: Request, context: DurableContext) => {
try {
const resultString = await context.waitForCallback(
"wait-for-external-input",
async (callbackId, ctx) => {
ctx.logger.info({ callbackId, request });
// submit data to external system
// provide callbackId and request data
await client.send(
new InvokeCommand({
FunctionName: process.env.CALLBACK_FUNCTION_ARN,
Payload: JSON.stringify({ callbackId, request }),
}),
);
},
{ timeout: { minutes: 5 } },
);
const result: { accepted: boolean } = JSON.parse(resultString);
return result;
} catch (error) {
if (error instanceof CallbackError) {
context.logger.error(error);
return { accepted: false };
}
// unexpected error or JSON parse error
throw error;
}
},
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment