Skip to content

api.runStore lets you persist values between steps within the same run. All keys are scoped to the current run and are deleted automatically when the run completes.

MethodDescription
api.runStore.get(key)Read a stored value (returns null if not set)
api.runStore.set(key, value)Write any JSON-serialisable value
api.runStore.push(key, item)Append an item to an ordered list
api.runStore.increment(key, delta?)Atomically increment a counter (default delta: 1)
api.runStore.delete(key)Remove a key

api.runStore is best for small run-scoped state such as:

  • IDs and keys
  • row numbers or chunk indexes
  • counters
  • warnings and compact error records
  • summary inputs for onWorkflowComplete

Do not use api.runStore as a cache for large raw datasets such as:

  • full parsed CSV row arrays
  • raw attachment text or buffers
  • entire imported API responses

For large files or imports, parse or import once, then pass compact references between steps such as chunk keys, row ranges, cursors, or counters.

Each stored value or pushed item should stay compact. Use run state for small operational data, not multi-megabyte payloads.

export class Workflow {
async start(data, headers, api) {
// Store the customer ID before scheduling the next step
await api.runStore.set('customerId', data.customer.id);
await api.scheduleNextStep({
delay: 10,
action: 'sendEmail',
payload: {},
});
}
async sendEmail(data, headers, api) {
// Retrieve the value stored in the previous step
const customerId = await api.runStore.get('customerId');
console.log('Sending to customer:', customerId);
}
}

Collecting results across fan-out branches

Section titled “Collecting results across fan-out branches”

api.runStore.push() is safe to call from concurrent parallel branches. Use it to append items without building your own shared array in memory:

export class Workflow {
async start(data, headers, api) {
// Fan out — schedule one branch per line item
for (const item of data.line_items) {
await api.scheduleNextStep({
delay: 10,
action: 'processItem',
payload: { item },
});
}
}
async processItem({ item }, headers, api) {
// Each parallel branch pushes its result
await api.runStore.push('results', { id: item.id, status: 'done' });
}
}

Do not use get() plus set() on the same key for shared aggregation in fan-out workflows. Parallel branches can race and overwrite each other. Use increment() for counters and push() for collected records instead.

api.runStore.increment() is safe for concurrent fan-out use. The optional second argument adds or subtracts that delta:

const newCount = await api.runStore.increment('processedCount');
// Decrement:
const newCount = await api.runStore.increment('processedCount', -1);

The method returns the new value after the increment.