Pace by queue depth
An upstream step releases new work only while the downstream queue is below a set depth, reading the depth with one counted query.
The situation
Cutting can produce parts faster than packing can handle. Flooding the packing queue hides urgent work under a pile, so cutting should hold back while packing has more than forty items waiting.
The recipe
export async function packingDepth(): Promise<number> { const res = await lt.escalations.searchByFacets({ role: 'packing', status: 'pending', limit: 1 }); return res.data?.total ?? 0;}const { packingDepth, releaseNextBatch } = Durable.workflow.proxyActivities<typeof activities>({ activities });
export async function cutRelease(envelope: { data: { maxDepth: number } }) { const depth = await packingDepth(); if (depth < envelope.data.maxDepth) await releaseNextBatch(envelope.data.maxDepth - depth); await Durable.workflow.sleep('1 minute'); await Durable.workflow.continueAsNew(envelope);}The depth is the total of a faceted search over the downstream role. Add facets to pace against a slice, such as one material.
The guarantee
total comes from the same WHERE as the page, so a limit: 1 read is the true count of pending rows the caller can see. Each tick reads live depth, so the release rate follows how fast the downstream role resolves. Machines on a line get the same behavior from queueDepth, enforced by the gateway. See Faceted routing.
Related patterns
The queue as a market
Two-sided dispatcher
Demand and supply are both rows. A dispatcher counts free supply, claims that much demand, locks the supply all-or-none, and pairs them.
The queue as a market
The list and the badge agree
The at-risk count on the Pace Board and the list it links to run the same SQL predicate, so the list always holds exactly that many rows.
The queue as a market
Claim complete groups
A consumer claims whole orders, every unit at once, and only orders whose units have all arrived. No order is ever split across consumers.
The physical world
A machine is a resolver
A workflow parks a row and waits; a machine resolves it over MQTT exactly as a person would from the dashboard.
