Skip to main content
Conditional flow enables your workflows to make decisions and follow different execution paths based on runtime conditions. This guide covers everything you need to know about building intelligent, branching workflows.

Overview

Conditional flow allows workflows to:
  • Branch execution based on runtime conditions
  • Route data through different processing paths
  • Skip nodes when conditions aren’t met
  • Implement business logic with if/else and switch/case patterns

Use Cases

Validation

Check data validity and route to error handling or success paths

Routing

Direct data to different processors based on type or status

Error Handling

Implement fallback logic when operations fail

Business Rules

Encode complex decision trees and approval workflows

Architecture

CrystalFlow’s conditional flow is built on three key components:

1. IConditionalNode Interface

Nodes implement this interface to enable branching:
The evaluateCondition() method:
  • Is called after the node’s execute() method runs
  • Returns the name of the output port representing the active branch
  • Must return a valid output port name (e.g., ‘thenOutput’, ‘elseOutput’, ‘case_0’, ‘default’)

2. ConditionalStep

The execution engine builds conditional steps for branching nodes:

3. Branch Execution

At runtime:
  1. The conditional node executes (via execute() method)
  2. evaluateCondition() is called to determine the active branch
  3. Only the matching branch’s steps execute
  4. Other branches are completely skipped
Only the active branch executes - inactive branches are never run, making conditional workflows efficient even with many branches.

Built-in Conditional Nodes

CrystalFlow includes two powerful conditional nodes out of the box.

IfNode

The IfNode provides classic if/else conditional logic:
Behavior:
  • condition = true → Routes to thenOutput (then branch)
  • condition = false → Routes to elseOutput (else branch)
  • Optional value input passes data through to active branch
Common Patterns:

SwitchNode

The SwitchNode provides multi-way branching with case matching:
Behavior:
  • Compares value against each case using strict equality (===)
  • Routes to matching case_X output
  • Falls back to default output if no match
  • Optional data input passes through to active branch
Dynamic Outputs: The cases property determines the number of outputs. When you add or remove cases, the node automatically updates its output ports.
Common Patterns:

Creating Custom Conditional Nodes

You can create custom conditional nodes for specialized branching logic:

Example: GreaterThanNode

Example: MultiConditionNode

For complex branching with multiple conditions:

Best Practices

Use descriptive output port names that clearly indicate what each branch represents. Good: ‘thenOutput’, ‘elseOutput’, ‘validOutput’, ‘invalidOutput’ Bad: ‘out1’, ‘out2’, ‘output’
Validate inputs and throw meaningful errors:
Always return a valid output port name. The execution engine will error if the returned value doesn’t match any output port.
Use JSDoc comments to explain what each branch represents and when it executes.

Branch Execution

Understanding how branches are built and executed is key to effective conditional workflows.

Plan Building

During workflow validation, the execution engine:
  1. Detects conditional nodes (nodes implementing IConditionalNode)
  2. For each output port of the conditional node:
    • Finds all downstream nodes connected to that port
    • Recursively builds execution steps for those nodes
    • Creates a ConditionalBranch with those steps
  3. Stores all branches in a ConditionalStep

Runtime Execution

When a conditional step executes:
  1. Execute the node: The conditional node’s execute() method runs
  2. Evaluate condition: evaluateCondition() is called to get the active branch
  3. Find matching branch: The engine finds the branch with matching condition
  4. Execute branch steps: Only the matching branch’s steps execute recursively
  5. Skip other branches: All other branches are completely ignored

Events

The execution engine emits events for branch execution:
Use branch events for:
  • Debugging which path your workflow takes
  • Visualizing execution flow in UI
  • Performance profiling of different branches
  • Logging business logic decisions

Nested Conditionals

Conditional nodes can be nested inside branches for complex decision trees:

If Inside If

Code Example:

Switch Inside If

Deep Nesting

CrystalFlow supports arbitrary nesting depth:
While CrystalFlow supports deep nesting, consider refactoring complex decision trees into smaller, reusable workflows for better maintainability.

Error Handling

Proper error handling ensures robust conditional workflows.

Invalid Branch Name

If evaluateCondition() returns a branch that doesn’t exist:
Result: Execution fails with:
Solution: Ensure return value matches an output port name:

Error Propagation

Errors inside branches propagate normally:
Handling Branch Errors:

Validation Errors

Conditional nodes should validate their inputs:
Always validate inputs in both execute() and evaluateCondition() for robust error handling.

Testing Conditional Workflows

Effective testing ensures your conditional logic works correctly.

Unit Testing Conditional Nodes

Integration Testing Workflows

Testing Nested Conditionals

Create “spy” or “mock” nodes that track whether they executed. This makes it easy to verify that only the expected branches ran.

Best Practices

Use dedicated logic nodes (CompareNode, IsPositiveNode) to compute boolean conditions. Keep conditional nodes focused on routing, not complex logic.
Use descriptive output port names: ‘validOutput’/‘invalidOutput’ is better than ‘output1’/‘output2’.
For SwitchNode, always handle the default case. Don’t assume value will always match one of your cases.
Write tests that exercise each branch of your conditional logic to ensure all paths work correctly.
Deeply nested conditionals are hard to maintain. Consider refactoring into smaller workflows or using switch nodes for multi-way branching.
Listen to branch events during development to understand which paths execute and debug unexpected behavior.

Examples

Conditional Logic Examples

See working examples with If and Switch nodes

Built-in Conditional Nodes

Complete API reference for IfNode and SwitchNode

Creating Custom Nodes

Learn to build your own conditional nodes

Execution Engine

Deep dive into execution plan architecture