Bun 1.4.2 fixes an AsyncLocalStorage leak: per-request Sume keys

Bun 1.4.2 fixes an AsyncLocalStorage leak from 1.4.1. Carry a per-request Sume Idempotency-Key in the store, and check your Bun version first.

4 min readSume
All posts

If your Bun server keeps a Sume Idempotency-Key in AsyncLocalStorage, upgrade to Bun 1.4.2 or later before you rely on it. The Bun v1.4.2 release notes describe a fix for an AsyncLocalStorage memory leak regression introduced in 1.4.1: a timer, immediate or promise created inside store.exit() or a nested store.run() kept the outer store alive. A store that holds per-request data and never gets released is a slow leak on a busy API.

The pattern itself is simple. Put the key for one incoming order into the store at the edge of the request, and let the function that calls Sume read it. That keeps the key out of every function signature, and every retry inside the request reuses the same value.

Why keep the key in the request context

Sume's rule is that the same key with the same payload returns the original job, while a different payload under the same key returns a 409, as the jobs and results docs explain. So the key should be a function of the order, not of the attempt. Deriving it once at the edge, for example order-<id>-v1, makes a retried HTTP request, a retried queue message and a retried function all land on the same job.

Fetching it from the store inside the submit function has a second benefit: a call made outside any request context throws instead of silently sending no key. A paid submit without a key cannot be deduplicated.

Bun release facts used here (read 2026-10-08)
FactDetailSource
Bun 1.4.2 release dateSep 5, 2026Bun release notes
Regression fixedAsyncLocalStorage leak introduced in 1.4.1Bun release notes
TriggerTimer, immediate or promise created in store.exit() or nested store.run()Bun release notes
Sume key ruleSame key and payload returns the original jobSume jobs docs

Steps

  • Check bun --version in CI and fail the build below 1.4.2 if you use AsyncLocalStorage on a long-running server.
  • Derive the key from a stable order id and a payload version at the entry point, then call als.run({ key }, handler).
  • Read the key in the one function that calls Sume. Throw when it is missing.
  • Bump the version suffix, for example -v2, only when the prompt or settings change on purpose.

Sample

This server derives a key from the order query parameter and submits an async image job. It was run on Bun 1.4.0 against a local stand-in for the API, and two concurrent requests kept separate keys. Set SUME_API_KEY to try it against the real API.

import { AsyncLocalStorage } from "node:async_hooks";
const base = process.env.SUME_BASE ?? "https://api.sume.com";
const als = new AsyncLocalStorage();
async function submitImage(prompt) {
  const key = als.getStore()?.key;
  if (!key) throw new Error("no Idempotency-Key in this request context");
  const res = await fetch(`${base}/v1/images`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SUME_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": key,
    },
    body: JSON.stringify({ model: "sume/auto", prompt, mode: "async" }),
  });
  return { status: res.status, key };
}
const server = Bun.serve({
  port: 0,
  fetch(req) {
    const order = new URL(req.url).searchParams.get("order") ?? "none";
    return als.run({ key: `order-${order}-v1` }, async () => {
      await new Promise((r) => setTimeout(r, 5));
      return Response.json(await submitImage("studio shot of a red kettle"));
    });
  },
});
const out = await Promise.all(["a1", "b2"].map((o) => fetch(`${server.url}?order=${o}`).then((r) => r.json())));
console.log(out);
server.stop();

What Sume does not do

Sume does not look at your server's request context and cannot make a key for you. If you use the TypeScript SDK, note that its client retries a POST only when an Idempotency-Key is present. Sume also does not tell you which Bun version leaks; that comes from the Bun release notes, so verify against your own build.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume