Skip to main content
General
Background Tasks

Vercel Workflows

Integrate Vercel Workflows with your application for serverless background tasks.

Open MarkdownFull AI corpusFeedback

Vercel Workflows runs durable TypeScript functions that can pause, retry and resume after a deployment or process failure. It is built on the open-source Workflow SDK.

Install and configure Workflow

Run the current setup command from the starter kit root:

Terminal
npx workflow@latest

The setup installs the workflow package and adds the required Next.js plugin. Review the resulting next.config.ts carefully because the starter kit already composes Content Collections, Fumadocs, Sentry and the bundle analyzer there. Preserve those wrappers when adding withWorkflow from workflow/next, then wrap the existing final configuration once. Running the setup a second time should update the integration, not add another wrapper.

Create a durable workflow

Keep orchestration in the workflow function and database or external-service I/O inside step functions. Pass a stored job ID rather than a browser-supplied user or organization object:

workflows/process-stored-job.ts
import { processStoredJob } from '@/lib/tasks/process-stored-job';

export async function processStoredJobWorkflow(jobId: string): Promise<void> {
  'use workflow';

  await processJobStep(jobId);
}

async function processJobStep(jobId: string): Promise<void> {
  'use step';

  await processStoredJob(jobId);
}

processStoredJob is product code you create. It should load the pending job and its organization from the database, claim it atomically and record success or failure. Make the operation idempotent because a step may be retried.

Workflow functions are deterministic orchestration code. Put database queries, Node.js APIs, ordinary fetch calls and third-party SDK calls in a use step function. Use Workflow's own durable primitives when the orchestration needs to sleep or wait for an external event.

Start the workflow after authorization

Start workflows through workflow/api. Do not call the workflow function directly:

app/api/tasks/process/route.ts
import { NextResponse } from 'next/server';
import { processStoredJobWorkflow } from '@/workflows/process-stored-job';
import { start } from 'workflow/api';
import { z } from 'zod/v4';

import { getSession } from '@/lib/auth/server';

const requestSchema = z.object({
  jobId: z.string().uuid()
});

export async function POST(request: Request): Promise<Response> {
  const session = await getSession();

  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const { jobId } = requestSchema.parse(await request.json());

  // Verify that session.user can start this stored job before continuing.
  const run = await start(processStoredJobWorkflow, [jobId]);

  return NextResponse.json({ runId: run.runId }, { status: 202 });
}

The authorization comment is a required product-specific step, not optional sample cleanup. Verify ownership or organization membership before starting the workflow. Re-check access in delayed steps when permissions may have changed.

Test the complete lifecycle

The Workflow CLI can verify the generated endpoints and inspect runs:

Terminal
npx workflow health
npx workflow web
npx workflow inspect runs

Test more than the successful path:

  1. An authenticated member can start a job they are allowed to operate.
  2. Another user cannot start the same organization's job.
  3. A transient step failure retries without repeating an external side effect.
  4. A permanent failure becomes visible and does not remain pending forever.
  5. Redeploying while a workflow is paused does not lose the run.
  6. Starting the same stored job twice does not process it twice.

On Vercel, inspect runs under Observability → Workflows. Keep application job state in the database as well so customers and support can see a stable product status without depending on provider-specific run details.

Production checklist

  • Pin a reviewed Workflow SDK version and update it deliberately.
  • Keep step inputs small and avoid secrets or complete customer records.
  • Log stable job and organization identifiers, not sensitive payloads.
  • Define which errors retry and which failures are permanent.
  • Add alerts for failed runs and jobs that remain pending too long.
  • Document how support can safely replay or cancel a job.
  • Review Workflow pricing and limits before launch.

Continue with the Workflow SDK documentation for sleep, hooks, streaming and other durable primitives.