Backend Development 9 min read

Designing a Flexible Workflow Engine: From Simple Chains to Complex Nested Nodes

This article chronicles the step‑by‑step evolution of a workflow engine, detailing how simple sequential approvers were expanded into hierarchical trees supporting parallel, multi‑sign, conditional, proxy, and scripted nodes, while introducing state management, rejection handling, and progress metrics.

Architect's Guide
Architect's Guide
Architect's Guide
Designing a Flexible Workflow Engine: From Simple Chains to Complex Nested Nodes

Level 1

The initial version implements a linear chain of approvers where each node records the current approver, moves to the next after approval, and ends when the final node is reached.

Level 2

Support for multi‑sign nodes is added; a multi‑sign node contains many approvers and only completes when all have approved. The design shifts from a simple linked list to a tree where leaf nodes are simple approvers and internal nodes represent complex structures.

Node states such as Ready, Complete, Future, and Waiting are introduced to control the flow.

Level 3

A parallel node is introduced; it is a complex node where any child node’s approval completes the whole node. A new state Skip is defined to deactivate sibling branches once one branch finishes.

Level 4

The tree structure is made fully recursive, allowing unlimited nesting of any node type, which enables arbitrarily complex workflows.

Level 5

Conditional nodes are added; they behave like parallel nodes but only activate child branches whose conditions evaluate to true based on form data.

Level 6

Simple nodes are classified into three approver types: fixed, derived from form fields, and computed via a mapping function (e.g., get_manager("Qian") ).

Level 7

Rejection to the initiator is implemented; only nodes in Ready state can reject, effectively restarting the workflow.

Level 8

Rejection to the previous approver is added, handling the complexity of nested nodes to locate the correct prior approver.

Level 9

Arbitrary‑node rejection is achieved by repeatedly rolling back until a Ready node matching the target is found.

Level 10

Time‑limit enforcement is added; nodes that exceed their allotted time are marked as timed‑out.

Level 11

Proxy (delegation) functionality is introduced by creating a parallel parent node and a sibling node for the proxy approver, allowing unlimited nesting of proxies.

Level 12

Cancellation of a proxy is implemented as the inverse operation, prohibited if the proxy has already approved.

Level 13

Pre‑ and post‑conditions are added to each node, requiring certain criteria before entry and before completion, significantly increasing code complexity.

Level 14

A progress metric is calculated as the distance from the leftmost node to the rightmost Ready node divided by the total distance, providing a percentage of workflow completion.

Level 15

Each node can now attach two executable scripts: one that runs when the node starts processing and another when it finishes.

Backendsoftware architectureState Managementworkflowapproval processnode design
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.