Workflow
@vitehub/workflow gives Vite and Nitro apps one way to define long-running work, start a named workflow from request code, and observe the run through Cloudflare Workflows or Vercel.
Use Workflow when background work has multiple steps, needs a stable run id, or should be visible after the request that started it has already returned.
import { runWorkflow } from '@vitehub/workflow'
import type { WelcomePayload } from '../workflows/welcome'
export default defineEventHandler(async (event) => {
const payload = await readBody<WelcomePayload>(event)
const run = await runWorkflow('welcome', payload)
return { ok: true, run }
})
import { defineWorkflow } from '@vitehub/workflow'
export type WelcomePayload = {
email: string
marker?: string
}
export default defineWorkflow<WelcomePayload>(async ({ payload }) => {
return {
message: `Welcome ${payload.email}`,
marker: payload.marker,
}
})
{
"ok": true,
"run": {
"id": "wrun_lvn4hx4f_x8k2p9s1",
"provider": "cloudflare",
"status": "queued"
}
}
What Workflow solves
Queues are a good fit for one handler. Workflows are better when the operation has an identity and the caller may need to ask what happened later.
Workflow keeps that boundary explicit:
Named flows
defineWorkflow() definition instead of scattering logic across request handlers.Portable starts
runWorkflow() or deferWorkflow() the same way on Cloudflare and Vercel.Run observation
Generated registry
One portable flow
The same application shape works across providers:
- Register the Vite plugin or Nitro module.
- Choose
cloudflareorvercelinworkflow.provider. - Define a named workflow with
defineWorkflow(). - Start it with
runWorkflow(name, payload). - Check it later with
getWorkflowRun(name, id)when the provider can report status.
Discovery model
Vite discovers workflow definitions from *.workflow.ts files and server/workflows/**.
The workflow name comes from the path without the .workflow suffix. src/email/welcome.workflow.ts becomes email/welcome. server/workflows/welcome.ts becomes welcome.
Supported providers
Start here
Start with Quickstart for the smallest complete setup. Use the primitive comparison when you are deciding between KV, Blob, Queue, Sandbox, Workflow, or inline request code.

