The Immortal Function: Inside vercel-labs/workflow-splitter

How compiler directives and durable execution are solving the brittle agent problem for serverless architectures.

7 min read • View on GitHub • More from vercel-labs

A precarious glass network of tubes where one shattered joint spills fluid, halting the entire machine. This illustrates how a single failure in a stateless system destroys the entire workflow.
In standard stateless serverless functions, a single timeout or crash destroys the entire process memory.
Key Takeaways

The Brittle Agent Problem

Serverless architectures and AI agents share a fatal flaw. They are fundamentally stateless and brittle. If a multi-step process fails halfway through, the entire state is often lost. Consider an e-commerce order with three items. If the inventory check for one item fails, you should not drop the entire order. Yet in a standard serverless function, a transient network timeout or a crash destroys the entire process memory.

If you have a complex agent running through a twenty-step process and the fifth step fails because of a network hiccup, you shouldn’t have to restart from scratch.

Peter Wielander, Principal Engineer at Vercel · Vercel’s Workflow DevKit Solves the Brittle Agent Problem

This is the problem Vercel aims to solve with its Workflow Development Kit (WDK) and the accompanying workflow-splitter repository. It demonstrates how to move durable execution out of heavy third-party SDKs and directly into native TypeScript syntax.

The Compiler as the Orchestrator

Instead of wrapping code in complex SDK boilerplate, developers use specific compiler directives. The magic lies in two strings: "use workflow" and "use step". This tells the underlying infrastructure to snapshot the state automatically.

import { workflow } from '@vercel/workflow';

export const orderSplitter = workflow('order-splitter', async (payload) => {
  'use workflow';
  const results = [];
  
  for (const item of payload.items) {
    // This step is durable and will retry automatically on failure
    const result = await processLineItem(item);
    results.push(result);
  }
  
  return results;
});

async function processLineItem(item) {
  'use step';
  // Atomic unit of work
  return await checkInventory(item);
}

Standard loops can now sleep, retry, and resume exactly where they left off. It is the React-ification of backend background jobs, making functions effectively immortal.

Anatomy of the Splitter

The repository provides a technical breakdown of this pattern in the workflows directory. It separates the orchestrator from the atomic unit of work. The orchestrator manages the high-level loop and aggregates results, while the step represents a retriable unit.

The Splitter pattern allows an orchestrator to manage partial success across parallel steps without losing global state.

The code handles errors with nuance. A FatalError, like insufficient stock, instantly halts the specific step and reports failure to the orchestrator. Transient errors, such as network timeouts, trigger automatic retries. The global state remains intact regardless of individual step failures.

Code as Live Documentation

The most unique feature of the repository is its Code Workbench. The Next.js application physically reads its own source code from the disk. It then maps the execution state via Server-Sent Events (SSE) and highlights the exact line of code currently executing in the UI.

A close-up of a wooden loom weaving rigid logic gates instead of yarn, illustrating ephemeral code logic being permanently woven into an immortal state history.
Durable execution permanently weaves ephemeral code logic into an unchangeable state history.

This turns business logic into a live observable dashboard. Users can watch an order move through lines of code in real-time, completely bypassing traditional log parsing.

The Durable Execution Landscape

Durable execution is not a new concept, but integrating it natively into the Next.js and TypeScript compiler is a significant shift. This syntax-first approach contrasts sharply with the infrastructure-first approaches of established players.

FeatureVercel WDKTemporalInngestTrigger.dev
Mental ModelCompiler DirectivesHeavy SDKEvent-DrivenBackground Jobs
State ManagementNative TS syntaxDeterministic constraintsEvent payloadsDatabase polling
Primary TargetServerless / AI AgentsEnterprise MicroservicesServerless integrationsAPI integrations
Setup ComplexityZero-config Next.jsRequires dedicated worker infrastructureDrop-in SDKDrop-in SDK

By solving the partial success problem at the compiler level, workflow-splitter demonstrates a future where developers can build resilient, long-running processes without managing complex queues or worker fleets.