Workflow State & Data Proxy
Relevant source files
The following files were used as context for generating this wiki page:
- packages/frontend/editor-ui/src/app/stores/workflows.store.ts
- packages/testing/playwright/CONTRIBUTING.md
- packages/testing/playwright/tests/ui/1-workflows.spec.ts
- packages/@n8n/ai-workflow-builder.ee/src/tools/prompts/main-agent.prompt.ts
- packages/@n8n/ai-workflow-builder.ee/src/tools/best-practices/document-processing.ts
- CONTRIBUTING.md
- packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiff.test.ts
The management of workflow state and data within the n8n frontend is primarily handled by a centralized Pinia store, workflows.store.ts. This store acts as the single source of truth for the currently loaded workflow, its execution data, and its metadata. It provides reactive state and actions for creating, updating, running, and managing workflows throughout their lifecycle, from the initial creation on the canvas to saving, execution, and debugging.
The system is designed to handle the complex state of a workflow, including its nodes, connections, settings, and associated execution results. It also manages interactions with the backend API for persistence and execution, and handles real-time updates via push events during a workflow run. Special considerations are made for handling different data types, such as binary data, and for development features like data pinning.
The workflows.store
The workflows.store.ts is a Pinia store that serves as the core of frontend workflow state management. It encapsulates the state of the current workflow, its execution history, and provides actions to interact with the backend.
Sources: packages/frontend/editor-ui/src/app/stores/workflows.store.ts
Core Responsibilities
- Current Workflow State: Holds the complete definition of the workflow currently being edited, including nodes, connections, settings, and metadata.
- Execution Management: Manages the state of workflow executions, including starting runs, receiving real-time data, and storing results.
- Data Pinning: Handles the pinning and unpinning of execution data to nodes for debugging and development.
- API Interaction: Contains actions for fetching, creating, saving, and deleting workflows via REST API calls.
- Lifecycle Management: Manages workflow lifecycle states such as active, inactive, and archived.
Key State Properties and Actions
The diagram below shows the main components of the workflows.store.
The following table summarizes some of the key reactive properties and actions available in the store.
| Property/Action | Type | Description |
|---|---|---|
workflow | ref<IWorkflowDb> | The currently loaded workflow object. |
workflowObject | ref<Workflow> | An instance of the Workflow class from the n8n-workflow package, used for complex operations like traversing the graph. |
workflowExecutionData | `ref<IExecutionResponse | null>` |
activeExecutionId | `ref<string | null |
isWorkflowRunning | computed<boolean> | A computed property that indicates if a workflow is currently executing. |
fetchWorkflow(id) | async function | Fetches a workflow from the backend and sets it as the current workflow. |
updateWorkflow(id, data) | async function | Saves changes to an existing workflow. |
createNewWorkflow(data) | async function | Creates a new workflow on the backend. |
runWorkflow(startRunData) | async function | Initiates a workflow execution. |
pinData(payload) | function | Pins execution data to a specific node. |
unpinData(payload) | function | Removes pinned data from a node. |
addNode(nodeData) | function | Adds a new node to the current workflow. |
removeNode(node) | function | Removes a node from the current workflow. |
addConnection(data) | function | Adds a connection between two nodes. |
removeConnection(data) | function | Removes a connection between two nodes. |
Sources: packages/frontend/editor-ui/src/app/stores/workflows.store.ts
Workflow Data Model (IWorkflowDb)
The IWorkflowDb interface defines the structure of a workflow as stored in the database and used throughout the frontend.
This ER diagram illustrates the main entities and their relationships within a workflow's data structure.
Key Properties
| Property | Type | Description |
|---|---|---|
id | string | The unique identifier for the workflow. |
name | string | The user-defined name of the workflow. |
nodes | INodeUi[] | An array of node objects that make up the workflow graph. |
connections | IConnections | An object describing the connections between nodes. |
settings | IWorkflowSettings | Workflow-level settings, such as executionOrder. |
pinData | IPinData | A map of node names to their pinned execution data. |
active | boolean | Indicates if the workflow is currently active and can be triggered. |
isArchived | boolean | Indicates if the workflow has been archived. |
versionId | string | The identifier for the current version of the workflow. |
Sources: packages/frontend/editor-ui/src/app/stores/workflows.store.ts:107-112, packages/frontend/editor-ui/src/features/workflows/workflowDiff/useWorkflowDiff.test.ts:161-183
Workflow Lifecycle
The lifecycle of a workflow involves creation, modification, saving, archiving, and deletion. These actions are managed through the UI and backed by actions in the workflows.store. The Playwright test suite provides a clear illustration of this lifecycle.
This flowchart shows the typical user-driven lifecycle of a workflow.
- Creation: A new workflow can be created from an empty state card or an "Add workflow" button. A unique name is typically assigned, often using
nanoidin tests to ensure uniqueness. - Saving: The workflow is saved via
canvas.saveWorkflow(), which triggers an API call to persist the state. - Management: In the workflows list view, users can search, filter by tags, archive, and unarchive workflows.
- Archiving/Deletion: Workflows must first be archived before they can be permanently deleted.
Sources: packages/testing/playwright/tests/ui/1-workflows.spec.ts:25-132
Execution State Management
When a workflow is executed, the workflows.store manages the incoming data and updates the UI in real-time.
Execution Flow
The following sequence diagram illustrates the process from initiating a run to updating the UI with results.
- Initiation: The user triggers an execution, calling the
runWorkflowaction in the store. - API Call: The store sends a
POSTrequest to the backend's/runendpoint. - Execution ID: The backend immediately returns an
executionId, which is stored by callingsetActiveExecutionId. - Real-time Updates: As the backend executes each node, it sends push events (e.g.,
nodeExecuteAfterData) to the frontend. - State Update: The
updateNodeExecutionStatusfunction processes these events, updating theworkflowExecutionDataref with the latest results for each node. - UI Reactivity: The UI, being reactively bound to the store's state, automatically updates to display the new execution data, node status, and results.
Sources: packages/frontend/editor-ui/src/app/stores/workflows.store.ts:1301-1342, packages/frontend/editor-ui/src/app/stores/workflows.store.ts:1455-1471
Data Handling
Data Pinning
Data pinning is a development feature that allows you to "freeze" the output data of a node. This is useful for developing and debugging downstream nodes without having to re-execute the entire workflow.
- The
pinDataaction in the store saves the provided data to theworkflow.value.pinDataobject, keyed by the node's name. - The
unpinDataaction removes it. - This
pinDataobject is part of the workflow definition and is saved along with the rest of the workflow. - The
dataPinningEventBusis used to notify other components of changes to pinned data.
Sources: packages/frontend/editor-ui/src/app/stores/workflows.store.ts:983-1033
Binary Data Management
Handling binary data (e.g., files from triggers or HTTP requests) requires special attention, as many nodes default to outputting JSON and will drop binary data.
The recommended pattern for preserving binary data while processing it is to use parallel branches and a Merge node.
- Referencing Binary Data: To access binary data from a previous node, use an expression like
{{ $('Node Name').item.binary.property_name }}. Theproperty_name(e.g.,data,attachment_0) depends on the source node. - Preservation: To prevent data loss, a common pattern is to split the workflow into two branches. One branch processes the data (e.g., extracts text), while the other does nothing, simply preserving the original binary item. The branches are then rejoined using a
Mergenode. - URL Generation: The
getBinaryUrlfunction in the store can be used to generate a temporary URL for viewing or downloading binary data associated with an execution.
Sources: packages/@n8n/ai-workflow-builder.ee/src/tools/best-practices/document-processing.ts:30-46, packages/frontend/editor-ui/src/app/stores/workflows.store.ts:1506-1517
Conclusion
The frontend state and data management for n8n workflows is robustly handled by the workflows.store.ts Pinia store. This central store manages the entire lifecycle of a workflow, from its structural definition to its real-time execution data. By providing a clear set of reactive properties and actions, it enables a responsive and predictable user experience in the workflow editor while abstracting away the complexities of API communication and real-time data synchronization. The established patterns for handling complex data types, like binary data, ensure that workflows can be built to handle a wide variety of use cases.