Batch handlers
Process several jobs of one type through a shared application call while preserving per-job outcomes.
Use TypeScript's Worker.handleBatch, Go's Worker.HandleBatch, or Python's
Worker.handle_batch when one application call can process several jobs more efficiently. Each
member keeps its own durable identity, lease, fence, retry budget, checkpoints, progress, and
cancellation.
worker.handleBatch("email.send", { maxSize: 20, lingerMs: 50 }, async (items) => {
const deliveries = await emailProvider.sendMany(items.map((item) => item.payload));
return deliveries.map((delivery) =>
delivery.error
? { status: "failed", error: delivery.error }
: { status: "succeeded", result: { providerId: delivery.id } },
);
});maxSize caps the group, while lingerMs lets a partial group wait briefly for peers. Claims still
pass through normal priority, queue, concurrency, keyed, and rate-limit admission, so a group can
remain partial until its linger ends.
The callback returns one ordered outcome per member. If it throws or returns an invalid list, Workhorse submits the failure for every member, then each job applies its own retry policy.
Python passes max_size and linger_ms as keyword arguments. Its callback returns mappings with
the same succeeded and failed statuses. Each item carries a BatchHandlerContext with
get_progress and set_progress.
Go passes MaxSize and Linger through BatchHandlerOptions. Its callback returns positional
BatchSucceeded or BatchFailed values, and each item carries a BatchHandlerContext with its
standard cancellation context, checkpoint operation, GetProgress, and SetProgress.
Workhorse records each shared invocation before the callback starts. The task drawer shows the batch size and links the other members. If the shared callback fails, the drawer identifies that failure across the group instead of guessing from the individual task errors.
Batch contexts omit timers, signals, human waits, and child joins because one member cannot suspend and replay independently inside a shared invocation. Register an ordinary handler when a job needs those boundaries.
TypeScript configures grouping with BatchHandlerOptions.maxSize and
BatchHandlerOptions.lingerMs; each option changes assembly of the batch without changing an
individual job's lifecycle.
Next
- Workers — size the capacity that batch members occupy
- Priority — order members before grouping
- Retries — apply failures per member
Exact batch limits and lifecycle rules: architecture reference.