Flow is two systems working together. Flow Studio is a 7-layer React/TypeScript frontend. Flow Engine is an ASP.NET Core orchestration engine. Here is how they are built.
Each layer can only depend on the layer below it. No upward dependencies. This makes every package independently testable and reusable.
Built on SOLID principles and Domain-Driven Design. The engine runs 60+ NodeExecutor types in a stack-based execution model with full persistence and real-time event streaming.
The public API. Accepts ExecuteProcessRequest and returns immediately with an ExecutionID. Actual execution runs in a background service scope — fire-and-forget. Clients receive progress via SignalR.
The core execution engine, split across 8 partial classes for maintainability. Manages the full lifecycle: process → thread → element execution with branching, routing, and event publishing.
Nodes are pushed onto a stack and popped for execution. After each node, the routing algorithm evaluates connection conditions and pushes the next node(s). Supports parallel branching by pushing multiple nodes.
Every execution carries a nested context: AppExecutionContext → ProcessExecutionContext → ProcessThreadExecutionContext → ProcessElementExecutionContext. Each level carries its own data, ID, and state.
All 60+ executors extend BaseNodeExecutor and follow a 3-part pattern: Validate (preconditions) → ExecuteInternalAsync (main logic) → Finalize (cleanup). Any exception returns a failed NodeExecutionResult with the error port.
Every execution, thread, and node result is persisted. Six core tables capture the full audit trail from start to finish.
Every workflow and every node moves through a defined set of states. Nothing is ambiguous.
Variables are scoped to the right level. Node output data is merged into the appropriate scope and passed forward automatically.
| Scope | Lifetime | Use for |
|---|---|---|
| GlobalScope | Entire workflow execution | Data shared across all threads and nodes — e.g. input parameters, final results |
| ThreadScope | One ProcessThread | Data local to a workflow thread — isolated from parallel branches |
| NodeScope | One node execution | Temporary working data for a single node — cleared after the node finishes |
| LoopScope | One loop iteration | Loop counter, current item — reset on each iteration |
| TryCatchScope | One try/catch block | Error information, rollback data — available in catch and finally blocks |
Capabilities extend what a node can do beyond its base execution logic. Each node declares which capabilities it needs. The engine validates availability before execution.