Why we model warehouse work as a graph, not a checklist
Real fulfillment is full of branches, retries and dead ends. Here's why Bonsai WMS treats picking and packing as a directed graph — a state machine — instead of a fixed list of steps.
Most warehouse software treats a process like a playlist. Step one, step two, step three, done. It's a comforting model because it's easy to draw and easy to build. It's also wrong about how fulfillment actually behaves.
Walk a pick path on a busy day and the straight line falls apart almost immediately. The bin is short two units. The barcode won't scan. The customer upgraded shipping after the order dropped. A marketplace sync fails halfway through. None of these are exotic edge cases — they are the job. Software that can only go forward, one step at a time, has nothing to say when reality forks.
A map, not a playlist
So in Bonsai WMS we model a process as a directed graph — a state machine — rather than a list. If a playlist is Spotify, this is Google Maps: there is a start, there is a destination, and there are many legitimate routes between them depending on what happens along the way.
A flow is made of nodes and the transitions between them. A node is one unit of work, and it's one of three kinds:
- Action nodes run server logic — reserve stock, write a transaction, call a carrier.
- Interaction nodes wait for a human — scan a bin, confirm a count, choose packaging. The flow pauses here and resumes when the input arrives.
- Logic nodes are invisible decisions — if quantity > 10, go left.
The interesting part is the transitions. Every node says not just "do this" but
"and here's where to go depending on how it went." Success goes one way. A
specific choice — Damaged, Short, Cancel — goes another. And every node
has an error path. That's what turns a brittle sequence into something that can
actually recover.
Recovery as a first-class citizen
Here's a concrete example. A pick flow calls out to a sales channel to confirm fulfillment, and the call fails. In a linear system the operator gets a red toast and the process halts — or worse, crashes and leaves state half-written.
In a graph, the failure is just another edge:
- Node
SyncToChannelsucceeds → go toFinish. SyncToChannelfails → go toRetryModal.RetryModalasks the operator: retry, or finish offline and reconcile later?- Each answer is its own transition.
The recovery logic lives in the flow definition, as data — not buried in code behind a feature flag. Because a flow is data, it's legible: you can reason about exactly what happens when something fails, instead of guessing.
Guardrails so it can't rot
Freedom to branch is also freedom to build something broken, so before a flow can be published it has to pass validation:
- Terminality — every path eventually reaches an end node. No dead ends.
- Reachability — no orphan nodes that nothing connects to.
- Loop safety — cycles are allowed (retries are loops!), but a tight infinite loop with no human step or delay is rejected.
The result is a system where a process can be as forgiving as the real world demands, without becoming a tangle nobody understands.
Why it matters
Modelling work as a graph isn't an academic preference. It's the difference between software that assumes the happy path and software that's honest about the messy one. The warehouse floor is the messy one. We'd rather our tools meet it there.
Building Bonsai WMS — operational software grown with patience and craft. Get in touch.