Skip to content

Repository files navigation

hono-wait-until TypeScript heart icon

npm version npm downloads Codecov Bundlejs jsDocs.io

hono-wait-until provides a waitUntil helper + middleware that make background/async work survive after the response returns.

It automatically falls through to the platform's native waitUntil (Cloudflare Workers, Deno, Bun, Netlify, Vercel Edge, ...) via c.executionCtx.waitUntil when available — no shim, no blocking.

On runtimes without a native waitUntil (Node, AWS Lambda, ...), it shims one: the middleware collects all wrapped promises and blocks until they settle before returning the response, so the platform won't kill your app with uncompleted async tasks.

Usage

Install package:

# npm
npm install hono-wait-until

# yarn
yarn add hono-wait-until

# pnpm (recommended)
pnpm install hono-wait-until

Import:

import type { WaitUntilList } from 'hono-wait-until'
import {
  waitUntil, // Optional helper function instead of accessing via context
  waitUntilMiddleware,
} from 'hono-wait-until'

const app = new Hono<{ Variables: { waitUntilList: WaitUntilList } }>()
  // Preferably, use the waitUntilMiddleware as early as you can.
  .use(waitUntilMiddleware())
  .get('/context', async (c) => {
    const waitUntilList = c.get('waitUntilList')
    waitUntilList.waitUntil(sleep(300))

    return c.text(`Using waitUntil via context variable`)
  })
  .get('/helper', async (c) => {
    waitUntil(sleep(300), c)

    return c.text(`Using waitUntil via helper function`)
  })

If any of the wrapped async tasks rejects, the middleware logs the errors and responds with a 500 (Some async tasks were rejected).

Native waitUntil fallthrough

On platforms that expose a native execution-context waitUntil (Cloudflare Workers, Deno, Bun, Netlify, Vercel Edge, ...), both waitUntil() and waitUntilMiddleware() delegate straight to c.executionCtx.waitUntil:

  • waitUntil() works without the middleware.
  • The middleware becomes a no-op (it will not block, since the runtime already keeps execution alive and reports errors itself).

On runtimes without native waitUntil (Node, AWS Lambda, ...), the middleware must be applied and will block until every wrapped task settles.

Options

continueWithoutSettled

Pass { continueWithoutSettled: true } to waitUntilMiddleware to respond immediately without blocking until all async tasks settle. This effectively disables the middleware and is useful when you have migrated to a platform that supports background async tasks, but want a test run without removing the waitUntil wrappers:

app.use(waitUntilMiddleware({ continueWithoutSettled: true }))

Releasing

Releases are version-first and dispatched by hand: one workflow run does the whole release, so a git push on its own never publishes anything.

  1. Go to Actions → Release → Run workflow and give it the version to ship, e.g. 2.2.0.
  2. .github/workflows/release.yml verifies the version, lints/type-checks/tests, then lets changelogen write the changelog, bump package.json, commit and tag v<version>. It pushes that commit and tag, creates the GitHub release, and publishes to npm with a short-lived OIDC token and --provenance.

Tick dry-run to do everything up to the commit and stop there — nothing is written back.

Locally, pnpm run release:check <version> validates a version against package.json, and pnpm run release:preview prints the changelog the next release would get.

One-time setup: publish the package once by hand (npm only offers a trusted publisher for a package that already exists), then on npmjs.com enable Settings → Publishing access → Trusted Publishing for NamesMT/hono-wait-until with the workflow filename release.yml.

Roadmap

  • Become the legendary 10000x developer

License License

MIT License © 2025 NamesMT

About

Keep background async work alive in Hono — native waitUntil on edge runtimes, a blocking shim on Node and AWS Lambda. Zero-dependency helper + middleware.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages