Portal Community

Depth Limit

The engine enforces a maximum nesting depth of 5 levels. A depth counter is tracked on each execution record via the SubWorkflowDepth field. When a SubWorkflow node attempts to start a child, the engine checks:

if (parentExecution.SubWorkflowDepth >= 5)
{
    throw new SubWorkflowDepthExceededException(
        $"Cannot nest sub-workflows deeper than 5 levels. Current depth: {parentExecution.SubWorkflowDepth}");
}

Cycle Detection

The engine prevents circular sub-workflow references at load time when a process is published. It builds a dependency graph of all processes and their sub-workflow references, then checks for cycles using DFS:


Process A → calls Process B → calls Process C → calls Process A  [CYCLE DETECTED]
Process A → calls Process B → calls Process C                    [OK]
  

A process with a circular dependency cannot be published. The designer shows a validation error indicating which process creates the cycle.

The Ancestry Chain

Each execution record stores its full ancestry chain:

{
  "executionId": "exec-103",
  "parentExecutionId": "exec-102",
  "rootExecutionId": "exec-100",
  "subWorkflowDepth": 3,
  "ancestorExecutionIds": ["exec-100", "exec-101", "exec-102"]
}

This ancestry chain enables the observer panel to display the full parent/child execution hierarchy.

Practical Nesting Example


Depth 0: PurchaseOrderApproval
    └── Depth 1: FinanceApproval (sync)
            └── Depth 2: DelegateApproval (sync)
                    └── Depth 3: SendApprovalNotification (async)
  

This 4-level hierarchy is well within the limit. The root workflow PurchaseOrderApproval calls FinanceApproval, which delegates to DelegateApproval, which fires an async notification workflow.

Design guidance: Avoid nesting more than 3 levels in most production workflows. Deep nesting makes debugging harder (more execution records to trace through) and increases end-to-end latency in sync mode. Consider flattening deep hierarchies by using async patterns with status polling.

Cross-Tenant Sub-Workflows

Sub-workflows always run within the same tenant as the parent. Cross-tenant invocation is blocked at the engine level — the tenantId is inherited from the parent execution and cannot be overridden by the SubWorkflow node config.