Run State
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.
Methods
Section titled “Methods”| Method | Description |
|---|---|
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 |
Use run state for compact data
Section titled “Use run state for compact data”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.
Passing data between steps
Section titled “Passing data between steps”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.
Atomic counters
Section titled “Atomic counters”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.