惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
量子位
T
Tailwind CSS Blog
Vercel News
Vercel News
I
InfoQ
Stack Overflow Blog
Stack Overflow Blog
U
Unit 42
Engineering at Meta
Engineering at Meta
L
LangChain Blog
大猫的无限游戏
大猫的无限游戏
D
Docker
博客园_首页
P
Proofpoint News Feed
月光博客
月光博客
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Martin Fowler
Martin Fowler
腾讯CDC
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

Workflow SDK Documentation

Patterns for Defining Tools Human-in-the-Loop Building Durable AI Agents Queueing User Messages Resumable Streams Sleep, Suspense, and Scheduling Streaming Updates from Tools API Reference Workflow Globals Changelog Resilient run start Cookbook Building a World Deploying Astro Express Fastify Hono Getting Started NestJS Next.js Nitro Nuxt Python SvelteKit Vite corrupted-event-log fetch-in-workflow hook-conflict Errors
Batching & Parallel Processing
2026-05-31 · via Workflow SDK Documentation

Process large collections in parallel batches with failure isolation between groups.

Use batching when you need to process a large list of items in parallel while controlling concurrency. Items are split into fixed-size batches, each batch runs concurrently, and failures in one batch don't affect others.

  • Bulk data imports (contacts, orders, products from a CSV)
  • Processing hundreds or thousands of items against external APIs
  • Calling rate-limited APIs where you need to control concurrency
  • Any fan-out where you want failure isolation between groups
  1. Records are split into fixed-size batches.
  2. Each batch runs in parallel via Promise.allSettled — failures in one record don't affect others.
  3. A sleep() between batches paces requests to avoid overloading downstream services.
  4. After all batches, a summary is returned with succeeded/failed counts.

The workflow splits records into chunks, processes each chunk concurrently, tracks results per batch, and returns a final tally.

import { sleep } from "workflow";

type Record = { name: string; email: string; role: string };

declare function processRecord(record: Record): Promise<string>; // @setup

export async function batchImport(records: Record[], batchSize: number) {
  "use workflow";

  let totalSucceeded = 0;
  let totalFailed = 0;

  for (let i = 0; i < records.length; i += batchSize) {
    const batch = records.slice(i, i + batchSize);

    // Run batch in parallel — failures are isolated per record
    const outcomes = await Promise.allSettled( 
      batch.map((record) => processRecord(record))
    );

    for (let j = 0; j < outcomes.length; j++) {
      if (outcomes[j].status === "fulfilled") {
        totalSucceeded++;
      } else {
        totalFailed++;
      }
    }

    // Pace between batches to avoid overloading downstream
    if (i + batchSize < records.length) {
      await sleep("1s"); 
    }
  }

  return { total: records.length, succeeded: totalSucceeded, failed: totalFailed };
}

Step function

Each record is processed in its own step with full Node.js access and automatic retries.

type Record = { name: string; email: string; role: string };

async function processRecord(record: Record): Promise<string> {
  "use step";
  const res = await fetch(`https://api.example.com/contacts`, {
    method: "POST",
    body: JSON.stringify(record),
  });
  if (!res.ok) throw new Error(`Failed to import ${record.email}`);
  const { id } = await res.json();
  return id;
}
  • Replace the Record type with your actual data shape (orders, images, products, etc.).
  • Replace processRecord() with your real import logic — DB upserts, API calls, file processing.
  • Tune batchSize and the sleep() duration to match your downstream rate limits.
  • Add or remove tracking as needed — the pattern works with any item type.
  • Use Promise.allSettled over Promise.all when you want to continue even if some items fail. Promise.all rejects on the first failure; allSettled waits for everything and tells you what failed.
  • Tune batch size to your downstream API limits. If the API allows 10 concurrent requests, use batchSize: 10.
  • Add pacing with sleep() between batches to respect rate limits. The sleep is durable — it survives cold starts.
  • Each processRecord call is an independent step. If one fails, it retries up to 3 times without affecting other items in the batch.