
Jacek Pietsch
Principal Solution Architect
A platform choice that looks like an implementation detail decides whether an organization can multiply the throughput of a core capability. The difference takes technical depth to see.

This is a technical article. The decision behind it is technical too, which is why it tends to get pushed down to engineers as an implementation detail. It is not an implementation detail. The consequences land in the business: in whether an organization can actually deliver on a strategic goal, and the goal here was to multiply the throughput of a core operational capability several times over. A platform chosen on the wrong grounds quietly caps how far that goal can reach, and nobody notices until the ceiling is already built.
The hard part is that this decision turns on a difference most buyers never see. Seeing it takes real technical depth, and that depth is usually absent at the level where the choice is signed off. A software comparison is only ever as good as the questions you ask, and the questions that matter most here cannot even be posed without understanding how each tool runs underneath. So the comparison gets made on the things anyone can read off a feature list, and on a feature list the two options below look almost identical.
A client of ours had to pick a platform to run a long-running business process. Two candidates. One was a real process engine, the Camunda class of tool, built to execute BPMN. The other was a low-code platform built on a state machine: a process is a set of named states with transitions between them, and a record moves from one state to the next when a condition is met.
Both list the same capabilities: workflows, subprocesses, parallel branches, timers, an API. On paper they are siblings. In execution they are not the same kind of thing, and the word that hides it most cleanly is "subprocess."
A state machine advances by moving a record between named states. It has no built-in notion of a token flowing through a graph, no identity for a particular run inside a flow, no concept of a parent that owns living children. A process engine executes a graph with tokens, and the engine itself tracks which run is where, which parent started which children, and how to unwind them if something goes wrong.
Same words on the box, different machines underneath. One backs "subprocess" with an execution model that tracks instances and hierarchy for you. The other gives you the word and leaves the tracking as your problem. This is exactly the kind of difference a feature list cannot show, and the kind you only meet once you ask the tools to coordinate moving parts. Our client met it the slow way, one surprising debugging session at a time, after the choice was made and the consequences had already reached into the architecture.
In the process we were building, a parent starts several child processes, waits for them, collects their results, and continues.
On the state machine, "wait for the children" is itself a state, guarded by a query over child records: is any child in a failed state. That query is not tied to this parent's specific children, nor to this particular attempt. A single failed child makes the parent give up and abandon the rest. A stale failed child from an earlier attempt poisons a restart, because nothing can tell an old child from a new one. Only one pass over one set of children is possible. Moving the parent on while it waits, to handle an outside event, is unsafe.
The consequence that hurt most: because the parent cannot reliably wait, the child has to reach back and push the parent forward. That means the child must know the parent's internal states and transitions. Every child ends up coupled to every parent that might start it.
That is not a subprocess feature. It is the absence of one, wearing the same name.
On the process engine, the same shape is a few modeling decisions. A call activity holds the parent while the child runs, and the engine resumes the parent automatically when the child finishes, because the engine owns the link. A set of children becomes a multi-instance activity where each child has its own identity and the whole set has a completion rule, so "wait for all" or "finish when enough succeed" is something you declare. A failing child raises a typed error caught next to the call, and the siblings keep running unless you decide otherwise. You move the parent on with a boundary event and the engine cleans up the children for you. The child never needs to know the parent exists.
Both tools said "yes" to subprocesses. For one that means a coordinated hierarchy the engine manages. For the other it means you rebuild that hierarchy by hand and carry the coupling forever.
None of this makes the state machine a bad tool. It is very good at what it is, state-driven records with human steps, and for many systems that is exactly enough. The point is the layer the decision was made on. "How does it run" is the question that separates the two categories, and it is precisely the question a feature comparison cannot hold. Asked "how" instead of "what," the two would not have looked alike for a moment, and the throughput goal that justified the whole project would have had a platform able to carry it.
Subprocess coordination is only one place the gap shows. Parallelism, timers and deadlines, versioning of running instances, error handling and compensation, message correlation: each looks like a single innocent line on a feature list, and each hides the same kind of category difference. We will take them one at a time in the next articles in this series.
Access our exclusive whitepapers, expert webinars, and in-depth articles on the latest breakthroughs and strategic implications of advanced automation and AI.