← Back to work

Workflow engine · 2016–2017

A Composable Workflow Engine

A workflow execution engine I designed from scratch for highly customized approval systems.

Complex approval rules were modeled as a composable tree of nodes with explicit execution states.

Role
Core architecture & implementation
Proof
  • Used in B2B OA delivery
  • Public design article
Stack
  • Python
  • Django
  • MySQL
Sequence
Approval
Parallel
Conditional

01 / Context

What did I build?

I designed and implemented a lightweight workflow execution engine for an OA system with highly customized approval rules.

The reusable engine was independent of the approval forms and business modules that used it.

Workflow engine overview showing four node types, five color-coded execution states, an ordered Sequence tree, and the re-evaluation cycle.
The complete model at a glance. Open the full-size diagram to inspect every node and state.
Read the diagram description

The diagram lists Simple Node, Sequence, Parallel, and Conditional as the four node types. READY uses a green border, COMPLETE blue, WAITING orange, SKIP gray, and FUTURE black. A WAITING Sequence orders Manager Approval, a COMPLETE Parallel, a WAITING Conditional, and a FUTURE Final Sign-off from left to right. Manager Approval is COMPLETE. The Parallel contains one COMPLETE Finance Approval and two SKIP branches for Legal and Director Approval. The Conditional selects a READY CFO Approval while Standard Finance is SKIP. The execution loop completes an approval node, re-evaluates the workflow instance, propagates state changes through the tree, and stops at a stable state.

workflow engine overview

Workflow engine overview showing four node types, five color-coded execution states, an ordered Sequence tree, and the re-evaluation cycle.

02 / Context

Why build our own workflow engine?

The team had already tried an open-source workflow framework, but in this project its complexity and customization cost made it difficult to maintain and hand over.

I took over the problem and redesigned the engine around a smaller model the team could understand and extend.

03 / Problem

What was actually hard?

The difficult part was not adding one more approval feature. It was finding an abstraction that could absorb continuously changing business rules without turning the system into a growing collection of special cases.

The goal was to make complexity emerge from composition, rather than from more special-case code.

04 / Design

How did I model a workflow?

I reduced the model to two conceptual categories of nodes: simple nodes represent approval work; complex nodes represent control flow.

Because complex nodes can contain other complex nodes, deeply nested workflows emerge naturally through composition.

Simple nodes represent work. Complex nodes represent control flow.

Composable structure

A small model, nested as deeply as needed

Sequence
Approval
Parallel
Approval
Approval
Sequence
Approval
Parallel
Conditional
Simple Node
Actual approval work associated with an approver.
Complex Node
Control flow such as sequence, parallelism, or a condition.

05 / Execution

How does the workflow know where it is?

The tree is not only a description of structure. Every node also carries an explicit execution state, so the engine can identify active work, completed work, future work, and branches that no longer participate.

Execution snapshot

Structure and runtime state live together

  1. SequenceWAITING
  2. Approval ACOMPLETE
  3. ParallelWAITING
  4. Approval BCOMPLETE
  5. Approval CREADY
  6. Approval DREADY
  7. Approval EFUTURE
FUTURE
Not active yet.
READY
Can currently be acted on.
WAITING
An active complex node waiting for child nodes.
COMPLETE
Finished.
SKIP
No longer participates in execution.
The same tree answers two questions: what is the workflow, and what can happen next?

06 / Algorithm

What happens after someone approves?

Every approval action changes one node, then the engine re-evaluates the workflow tree. State transitions propagate through the structure until no node changes anymore.

Evaluation sequence

One action can advance several nodes

  1. 01
    Approval B

    READYCOMPLETE

    The approval action changes one node.

  2. 02
    Parent rule

    WAITINGCOMPLETE

    The parent is evaluated against its children.

  3. 03
    Sequence advances

    FUTUREREADY

    A following node becomes actionable.

  4. 04
    Evaluate again

    Changed states can trigger another pass through the tree.

  5. 05
    Stable

    Evaluation stops when a full pass produces no state changes.

Evaluation repeats only while a node changes; a stable tree ends the cycle.

07 / Evolution

Did the abstraction survive real requirements?

New requirements kept arriving, from parallel approval and arbitrary nesting to rollback, delegation, conditions, progress calculation, and node hooks.

The implementation gained capabilities while the core abstraction remained nodes + composition + state + evaluation.

Requirements changed. The model did not need to be replaced.
  1. Linear approval
  2. Parallel approval
  3. Nested workflows
  4. Conditions
  5. Dynamic approvers
  6. Rollback
  7. Delegation
  8. Runtime tree mutation

Used in productionThe engine was used in B2B OA deployments, including internal approval systems for securities and financial companies.

08 / Runtime mutation

What happened when the workflow itself had to change at runtime?

Delegation changed the execution structure after a workflow had already started. Instead of adding delegation-specific fields and branches to an approval node, the engine could express it with the existing composition model.

When Mike delegated to Alice, the original node became an AnyOf containing both approvers. Cancelling delegation could reverse the same structural change.

Before / after

Delegation as a tree transformation

Before

Parent
Mike

After Mike delegates to Alice

Parent
AnyOf
Mike
Alice
The existing composition model represents the new runtime structure without delegation-specific branches inside an approval node.

09 / Reflection

What do I still like about this design today?

Some surrounding implementation details, including persistence, were fairly rough and are not the focus of this case study.

What still holds up is the core move: turning messy business rules into a small composable data structure plus an execution algorithm.

Years later, the part I would still defend is the core model: composable nodes, explicit state, and deterministic evaluation rules.

This was an employer-owned production system. Architecture and implementation details shown here are simplified to protect confidential information.