Skip to content

docs: add JavaScript runtimes page - #247

Draft
ParidelPooya wants to merge 7 commits into
mainfrom
docs/javascript-runtimes
Draft

docs: add JavaScript runtimes page#247
ParidelPooya wants to merge 7 commits into
mainfrom
docs/javascript-runtimes

Conversation

@ParidelPooya

@ParidelPooya ParidelPooya commented Aug 11, 2026

Copy link
Copy Markdown

Adds a new top-level Guides section with its first page: how to deploy a
durable function on each JavaScript runtime, meaning the managed Node.js runtime
and container images carrying Bun, Deno, or LLRT.

The page started under SDK Reference, in the TypeScript language guide, but it is
a deployment guide rather than API reference, so it now sits at
docs/guides/javascript-runtimes.md with a section index alongside it, matching
how every other section is built. Guides is the last top-level section.

The premise is that the Durable Execution SDK talks to the service over the
ordinary Lambda data plane, so it needs nothing from the runtime beyond normal
handler invocation. That makes any JavaScript runtime you can put in a container
image a candidate. The page recommends starting with the managed Node.js runtime
and frames the rest by the work they add, not by any support status.

What it covers

  • The execution role, the qualified-ARN requirement for durable execution ARNs,
    and the two different timeouts (timeout per invocation, executionTimeout
    per execution)
  • CDK for NodejsFunction and DockerImageFunction using the durableConfig
    property, plus the CfnFunction property override for versions of
    aws-cdk-lib that predate it
  • Dockerfiles for Bun, Deno, and LLRT, and why Bun and Deno each need a Runtime
    API loop while LLRT does not
  • llrt compile, which precompiles the handler to bytecode and removes about a
    quarter of LLRT's cold init
  • The bundling differences per runtime, including the CommonJS interop banner
    that Deno requires and Bun hides
  • What LLRT gives up without AsyncLocalStorage, and how replay cost grows
    without a JIT compiler

How it was verified

Every runtime ran the same durable function on Lambda in us-east-1: steps, a
step that failed once and retried, a 30 second wait, a child context, and a
parallel block. All four completed across three invocations and returned
identical results.

Measurements are the median of three cold starts per runtime, each on a fresh
function version, after a discarded warm-up execution so no figure includes a
first-ever image pull.

Artifact Cold init First invocation Warm invocation Peak memory
Managed Node.js 22 0.2 MB zip 276 ms 714 ms 180 ms 102 MB
Bun 202 MB image 385 ms 635 ms 238 ms 204 MB
Deno 195 MB image 462 ms 875 ms 258 ms 118 MB
LLRT, bytecode 17 MB image 29 ms 187 ms 147 ms 31 MB

Both CDK snippets were confirmed by synthesis rather than written from memory.
They produce DurableConfig: {"ExecutionTimeout": 3600, "RetentionPeriodInDays": 7}, and the durableConfig property and the CfnFunction override emit
identical CloudFormation.

zensical build reports no issues, mdformat is clean, and the internal links
plus the #create-the-execution-role anchor resolve in the built site.

The measurements were wrong in the first revision, and are now fixed

The first revision of this page reported LLRT cold-starting in 1627 ms and
concluded that it "starts slowest despite starting fastest as a process". Both
came from taking a single sample per runtime, where the first invocation of a
brand new image includes the initial image pull.

Re-measured properly, LLRT starts in 29 ms, roughly an order of magnitude faster
than the managed Node.js runtime, and the earlier conclusion is gone. Bun and
Deno also moved, and the managed Node.js baseline that was missing is now
present.

Merge order has cleared

The page states that LLRT needs @aws/durable-execution-sdk-js 2.3.0 or later.
That version is now latest on npm and contains the capability fallbacks from
aws-durable-execution-sdk-js#817,
so nothing gates the merge on release timing any more.

Notes on llrt compile

Worth flagging because the constraints are surprising and undocumented upstream.
Precompiling requires the CLI build (llrt-linux-arm64-full-sdk.zip), not
llrt-container-arm64-full-sdk:

  • The container build refuses the subcommand, reporting
    Not supported in "lambda" version.
  • LLRT compresses bytecode with a zstd dictionary that each build trains from its
    own embedded sources, so bytecode from one build fails to load in another with
    IO Error: Dictionary mismatch. Deploying CLI-compiled bytecode onto the
    container build fails at init.

Compiling inside the image with the same binary that runs the function satisfies
both. The CLI build carries the Lambda bootstrap too, so no custom entrypoint is
needed. Both facts look worth raising upstream on awslabs/llrt.

Convention notes

The repository requires code samples in all four languages under examples/.
This page is JavaScript-specific by subject and keeps its snippets inline. They
are CDK and Dockerfiles rather than SDK usage, so there is no meaningful Python,
Java, or C# equivalent. Happy to move them under examples/typescript/ if you
would prefer them as included files.

Guides is a new top level, so it is worth agreeing on the boundary between it
and Patterns before more pages land there. My reading: Patterns is about how
to write durable code, Guides is about how to build, package, and deploy it.

The page also mentions that one rule in
@aws/durable-execution-sdk-js-eslint-plugin crashes on ESLint 10, which is
accurate but reads oddly in customer documentation without an issue to point at.
Say the word and I will drop it and file an issue on the SDK repository instead.

Document deploying durable functions on the managed Node.js
runtime and on container images carrying Bun, Deno, or LLRT.

- Cover the execution role, qualified-ARN requirement, and the
  two timeouts that apply to a durable function
- Add CDK for both NodejsFunction and DockerImageFunction,
  plus the CfnFunction override for older aws-cdk-lib
- Record the bundling differences per runtime, including the
  CommonJS interop banner that Deno requires
- Note what LLRT gives up without AsyncLocalStorage, and the
  replay cost that grows without a JIT
The published cold start figures came from a single sample each, so
a first-ever image pull was recorded as a runtime characteristic.
Re-measured with three cold starts per runtime after a discarded
warm-up, plus the managed Node.js baseline that was missing.

- LLRT starts in 29 ms, not 1627 ms, and the page no longer claims
  it starts slowest
- Add the managed Node.js baseline: 276 ms init, 102 MB
- Document llrt compile, which removes a quarter of LLRT cold init,
  and the two constraints on which binary can produce the bytecode
The replay row carried "best" for Node.js and "not measured" for
Bun and Deno. Node.js is not best: Bun and Deno replay faster once
histories grow.

- Replace the row with measured CPU at 4004 operations
- Explain what replay is and how the figures were produced
- Add the builtin-prefix rewrite Deno needs when builtins stay
  external
The page is a deployment guide, not TypeScript API reference, so it
reads oddly nested under SDK Reference. Promote it to a new
top-level Guides section, placed after Getting Started.

- Move to docs/guides/javascript-runtimes.md and fix link depth
- Add a Guides section index, matching every other section
- Restore the flat TypeScript entry in the nav
The Dockerfile tab bodies sat inside outer fences at column 0, so
pymdownx.tabbed produced three empty one-tab widgets and leaked the
fence into the output. Indent the bodies four spaces, matching
custom-lambda-client.md. Now one three-tab group, verified in the
built HTML.

- Format with mdformat-gfm and mdformat-mkdocs, the plugin set CI
  installs; a bare mdformat does not pad tables and passed falsely
- Add bootstrap.mjs, without which neither Bun nor Deno deployment
  can be completed, and the LLRT binary download step
- Add the missing CDK imports and use Platform from aws-ecr-assets
- Name aws-cdk-lib 2.232.0, where L1 and L2 support landed together
- Keep operation counts under 3000
- Move the figures into one dated block and make the prose
  qualitative, so three tables no longer repeat them
- Drop the unexplained LocalDurableTestRunner row and explain in
  prose that the runner runs on your machine, not on Lambda
- Label the leading header cell in every table
@ParidelPooya
ParidelPooya deployed to ai-pr-review August 12, 2026 21:44 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants