Vercel Workflows
Integrate Vercel Workflows with your application for serverless background tasks.
Vercel Workflows is a serverless workflow orchestration platform that lets you build reliable, long-running background tasks directly on Vercel's infrastructure. It's perfect for applications already deployed on Vercel.
Why Vercel Workflows?
Vercel Workflows provides a native solution for background tasks if you're already using Vercel for hosting. It integrates seamlessly with your existing Vercel deployment and provides automatic retries, scheduling, and monitoring.
Setup
Vercel Workflows is available as part of your Vercel deployment. To get started:
- Ensure your project is deployed on Vercel
- Install the Vercel Workflows SDK:
npm install @vercel/workflowsConfigure environment variables
Add your Vercel Workflows credentials to your environment variables:
VERCEL_WORKFLOWS_SECRET=your_workflows_secret_hereYou can find this in your Vercel dashboard under your project settings.
Create your first workflow
Create workflows in a workflows directory:
import { workflow } from '@vercel/workflows';
export const processUserData = workflow(
'process-user-data',
async (input: {
userId: string;
operation: 'export' | 'analyze' | 'cleanup';
}) => {
const { userId, operation } = input;
console.log('Starting user data processing', { userId, operation });
switch (operation) {
case 'export':
// Export user data
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log('User data exported successfully');
return { success: true, result: 'Data exported to CSV' };
case 'analyze':
// Analyze user data
await new Promise((resolve) => setTimeout(resolve, 5000));
console.log('User data analysis completed');
return {
success: true,
result: { totalActions: 156, avgSessionTime: '4m 32s' }
};
case 'cleanup':
// Cleanup user data
await new Promise((resolve) => setTimeout(resolve, 3000));
console.log('User data cleanup completed');
return { success: true, result: 'Removed 23 obsolete records' };
default:
throw new Error(`Unknown operation: ${operation}`);
}
}
);Create a scheduled workflow:
import { schedule, workflow } from '@vercel/workflows';
export const dailyCleanup = workflow('daily-cleanup', async () => {
console.log('Starting daily cleanup');
// Cleanup old logs
await new Promise((resolve) => setTimeout(resolve, 5000));
console.log('Logs cleaned up');
// Cleanup temporary files
await new Promise((resolve) => setTimeout(resolve, 3000));
console.log('Temp files cleaned up');
// Generate daily reports
await new Promise((resolve) => setTimeout(resolve, 8000));
console.log('Reports generated');
return {
success: true,
cleanupTime: new Date().toISOString(),
itemsProcessed: 1247
};
});
// Schedule the workflow to run daily at 2 AM
schedule(dailyCleanup, {
cron: '0 2 * * *'
});Triggering workflows
From an API route
import { NextRequest, NextResponse } from 'next/server';
import { getWorkflowClient } from '@vercel/workflows';
import * as z from 'zod';
import { getSession } from '@/lib/auth/server';
const processUserDataSchema = z.object({
userId: z.string(),
operation: z.enum(['export', 'analyze', 'cleanup'])
});
export async function POST(request: NextRequest) {
const session = await getSession();
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const body = await request.json();
const { userId, operation } = processUserDataSchema.parse(body);
const client = getWorkflowClient();
const handle = await client.trigger('process-user-data', {
userId,
operation
});
return NextResponse.json({
success: true,
workflowId: handle.id,
message: 'Background task started successfully'
});
}From a server action
'use server';
import { getWorkflowClient } from '@vercel/workflows';
import { getSession } from '@/lib/auth/server';
export async function processUserData(
userId: string,
operation: 'export' | 'analyze' | 'cleanup'
) {
const session = await getSession();
if (!session) {
throw new Error('Unauthorized');
}
try {
const client = getWorkflowClient();
const handle = await client.trigger('process-user-data', {
userId,
operation
});
return {
success: true,
workflowId: handle.id
};
} catch (error) {
console.error('Failed to trigger background task:', error);
throw new Error('Failed to start background task');
}
}Monitoring and debugging
Visit the Vercel Dashboard to monitor your workflows:
- View workflow execution logs and performance metrics
- Track success and failure rates
- Monitor workflow duration
- Replay failed workflows
- Set up alerts for workflow failures
Best practices
Use descriptive workflow IDs
// ✅ Good
workflow('user-data-export-csv', async () => {});
// ❌ Not so good
workflow('task1', async () => {});Handle errors gracefully
workflow('process-data', async (input) => {
try {
return await processData(input);
} catch (error) {
console.error('Processing failed:', error);
throw error; // Re-throw to trigger retry
}
});Use structured logging
console.log('Workflow started', {
workflowId: 'process-user-data',
userId: input.userId,
operation: input.operation,
timestamp: new Date().toISOString()
});Next steps
With Vercel Workflows integrated into your application, you can now:
- Handle long-running operations that would timeout in serverless functions
- Schedule recurring tasks like reports, cleanups, and maintenance
- Process background jobs reliably with automatic retries
- Monitor workflows directly in your Vercel dashboard
Ready to explore more? Check out the official documentation for advanced features like workflow composition, event triggers, and more.