Pranay Prakash efbdc213a0 [core] Make hook.metadata a lazy Promise getter (#3988)
* [core] Make `hook.metadata` a lazy Promise getter

Hydrating a hook's metadata is a decrypting READ: it needs the owning
run's payload keys, and resolving those costs a run fetch plus a
`run-key` API round trip (~350ms). `getHookByToken()` did that work
eagerly on every lookup that found a metadata-bearing hook, so callers
that only wanted `runId`/`token` — and hook resumption, which never
reads metadata at all — paid for it anyway.

`metadata` is now a getter returning a memoized Promise, the same shape
as `run.returnValue`. The lookup is one read again; hydration and the
key resolution behind it happen on first access, or never.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Co-Authored-By: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>

* docs: surface the lazy hook.metadata change in What's new, the migration skill, and the resumeHook reference

Adds the breaking-change row to the v5 What's new page and puts that page
in the sidebar as the first visible entry (the /v5/docs redirect to
getting-started is unchanged). Teaches the migrating-workflow-v4-to-v5
skill the `await hook.metadata` rewrite and bumps its version. Points the
resumeHook reference at HookWithLazyMetadata, and notes on the World
storage page that world.hooks.getByToken() returns raw serialized
metadata.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* [core] Export the lazy-metadata hook type as `Hook` from `workflow/api`

`getHookByToken()` and `resumeHook()` return `Hook`, not a separate
`HookWithLazyMetadata`: one public hook type whose `metadata` is a lazy
Promise, mirroring `Run` for runs. The World-level record from
`@workflow/world` is unchanged and is referenced as `WorldHook` inside the
runtime.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* [core] Define the lazy `metadata` getter in place; tighten changeset and docs wording

Review feedback: the hook record a World returns is a fresh object per
lookup and the eager path mutated it anyway, so define the getter on it
directly instead of copying it with Object.create(). The changeset is one
sentence, and the docs describe hydration as extra network round trips
rather than decryption, since not every World encrypts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: Pranay Prakash <1797812+pranaygp@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 12:26:28 -07:00
2025-10-23 12:07:52 +03:00
2025-10-23 12:07:52 +03:00
2025-10-23 12:07:52 +03:00
2025-10-23 12:07:52 +03:00
2025-10-23 12:07:52 +03:00

Workflow SDK logo

Workflow SDK

Vercel logo npm version License Join the community on GitHub

Workflow SDK makes TypeScript and JavaScript functions durable. It persists workflow progress, retries failed steps, and provides built-in observability. Workflows can suspend without using compute while they wait.

Quick start

Install the SDK in an existing project:

npm install workflow

Configure the integration for your framework. For example, with Next.js:

// next.config.ts
import { withWorkflow } from 'workflow/next';

export default withWorkflow({});

Then start a workflow from an API route, Server Action, or other server-side code:

import { start } from 'workflow/api';
import { onboardUser } from './workflows/onboard-user';

await start(onboardUser, ['hello@example.com']);

Run your app, then open the local observability UI in another terminal:

npm run dev
npx workflow web

Choose your framework in the getting-started guides.

Note

The workflow package includes its full documentation, so coding agents can read version-matched guides locally from node_modules/workflow/docs.

Run anywhere

Local development uses the bundled backend with no configuration. Deploy to Vercel for managed storage, queuing, scaling, and observability. To self-host, use the Postgres backend or implement a custom World.

The Worlds page lists maintainer-curated third-party Worlds, including self-hosted and managed options. Submit your World by updating the Worlds Manifest.

Community

The Workflow SDK community lives on GitHub Discussions, where you can ask questions, share ideas, and show what you have built.

Contributing

Contributions are welcome. Use issues and discussions to collaborate with the team and wider community. By participating, you agree to our Code of Conduct.

Security

If you find a security vulnerability in Workflow SDK, disclose it responsibly instead of opening a public issue.

To participate in our Open Source Software Bug Bounty program, please email responsible.disclosure@vercel.com. We will add you to the program and provide further instructions for submitting your report.

S
Description
workflow: Creates durable, resumable workflows using Vercel's Workflow SDK. Use when building workflows that need to survive restarts, pause for external events, retry…; workflow-init: Install and configure Vercel Workflow SDK before it exists in node_modules. Use when the user asks to "install workflow", "set up workflow", "add durable…
Readme 140 MiB
Languages
TypeScript 88.8%
JavaScript 5.9%
Rust 4%
CSS 0.5%
Python 0.4%
Other 0.3%