Really interesting framework for thinking about backend systems. I've been messing around with LLMs, and there's a real need to check and constrain outputs when building anything rigorous. I've only been working through static workflows, but can imagine it only gets more complex if the workflow changes dynamically based on the LLM output. I wonder if this state-machine-based back end is a good way to better manage that.
Great point! State machines are a really nice way to orchestrate multi-step LLM invocations.
They're also a great way for LLMs to produce code. It's human-readable so you can vet that it's doing what you want it to and it's high-level enough that the remaining bits to fill in tend to be small functions that AI can easily generate.
Great post. I really like the idea of explicitly enumerating all state possibilities for a correctness guarantee. This seems spot on for how I want to think about distributed systems.
Am I right in assuming this solution is somewhere in between distributed tracing and Workflow definition, like event based programming, but the possible states are always strongly typed / defined?
I've also been thinking a lot about node-based programming, in a creative context. One piece I keep coming back to is that node trees are really helpful when the logic is straightforward, but can be a bit visually overwhelming for first timers when the logic is nontrivial or it generates complex artifacts as an output. Does State Backed support grouping nodes, a la Blender or Houdini? Or how do you think about information hiding for this type of thing? Looks like right now the nodes represent functions, so you don't have to think about what sendWelcomeEmail does, eg. How do you think about representing the state within that logic then?
It's very similar to a DAG you'd make for a workflow but not necessarily acyclic and events can be sent from external sources as well as internal processes.
States can be grouped into parent states, which gives you some additional nice things like parallel states and also a totally reasonable way to zoom out and hide info in visualizations.
When you have a pure function or a single effect, that should definitely just be a function rather than its own machine. Sate machines are most useful for orchestrating those effectful functions and for situations where you want to accept external events. So you're still writing regular code but you're writing it in small functions that get invoked by the state machine as needed.
That is, state machines don't replace code. They're just a really nice way to organize it.
The systems available today (Temporal/Cadence/etc) definitely make a big mess of updating logic/code. This seems so obvious and yet I've not seen it done well -- excited to see where it goes!
Also my first time hearing of the Slemiel the painter algorithm (or at least first time hearing it described that way). Thanks for sharing
I found the contrast with workflow systems such as Cadence/Temporal really interesting. You can tell the author has felt the pain of managing real time distributed state machines.
state machines are a lost art and most of the issues that make it hard to grok for engineers is the lack of good debugging and visual tools. excited to try this out!
They're also a great way for LLMs to produce code. It's human-readable so you can vet that it's doing what you want it to and it's high-level enough that the remaining bits to fill in tend to be small functions that AI can easily generate.
Am I right in assuming this solution is somewhere in between distributed tracing and Workflow definition, like event based programming, but the possible states are always strongly typed / defined?
I've also been thinking a lot about node-based programming, in a creative context. One piece I keep coming back to is that node trees are really helpful when the logic is straightforward, but can be a bit visually overwhelming for first timers when the logic is nontrivial or it generates complex artifacts as an output. Does State Backed support grouping nodes, a la Blender or Houdini? Or how do you think about information hiding for this type of thing? Looks like right now the nodes represent functions, so you don't have to think about what sendWelcomeEmail does, eg. How do you think about representing the state within that logic then?
It's very similar to a DAG you'd make for a workflow but not necessarily acyclic and events can be sent from external sources as well as internal processes.
States can be grouped into parent states, which gives you some additional nice things like parallel states and also a totally reasonable way to zoom out and hide info in visualizations.
When you have a pure function or a single effect, that should definitely just be a function rather than its own machine. Sate machines are most useful for orchestrating those effectful functions and for situations where you want to accept external events. So you're still writing regular code but you're writing it in small functions that get invoked by the state machine as needed.
That is, state machines don't replace code. They're just a really nice way to organize it.
Also my first time hearing of the Slemiel the painter algorithm (or at least first time hearing it described that way). Thanks for sharing
The old Joel on Software blog has some gems.
I think the author does a good job here showing why the state machine might just be that abstraction.