Run State Store and share data across steps within a single workflow run. 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 | 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 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 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 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 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. Note: Run state is scoped to a single run. It cannot be shared between different workflow runs. For cross-run persistence, write to Shopify metafields or an external store via fetch().