Workflow SDK adds idempotent starts
Vercel’s Workflow SDK now offers an atomic start() function that prevents duplicate workflow runs by safely claiming hooks in a single step, replacing a previous two-step process.
The Workflow SDK’s start() function has been updated to perform an atomic operation that both admits a run and claims a hook in one step, eliminating the risk of duplicate workflow starts. Previously, the process required a separate getHookByToken() call followed by start(), which created a documented race condition where duplicate starts could occur between the two steps. The new atomic approach ensures that the claimed hook exists immediately upon run admission, allowing resumeHook to function even before execution begins and enabling ordered buffering of early payloads.
With the update, the createHook({ token }) method inside the workflow binds to an already-claimed hook when provided with the same token, guaranteeing no new hook is registered and no additional steps are added. The token acts as an idempotency key, sourced from identifiers such as order IDs, invoice IDs, import IDs, or request IDs, and ensures that only one run can own it. If a duplicate start() is attempted, a HookConflictError is thrown, carrying the conflicting run ID of the owner, and the duplicate run is never created.
The token’s role as an idempotency key means the workflow does not need to open the hook at all; if the hook remains unused, the token serves solely as an idempotency mechanism, and the run completes normally without additional overhead. This design simplifies workflow logic by removing the need for explicit hook management in cases where idempotency is the primary requirement.
To implement the new atomic start() function, users must upgrade to workflow version 5.3.1 and review the updated idempotency documentation for guidance. The experimental_minRetention setting further enhances idempotency by keeping the token unavailable for a set period after the run ends, counted from the start() call, to prevent late duplicate starts from being accepted.