Most people are familiar with state machines and know their value. The average state machine library can help you model states, prevent invalid transitions, and produce diagrams that help even non-technical people understand how the code behaves.
This article isn’t about making the case for state machines. It’s about how you take the concept of a state machine and have it work alongside your database models, leveraging your relational database (say Postgres or MySQL) to help you build concurrent-safe and efficient software.
I first encountered this pattern when I joined GoCardless in 2015. Processing bank payments is a multi-day affair and extremely stateful, so it’s no surprise that the team eventually built a library called Statesman that provided a state machine powered by underlying transition tables.
Most of GoCardless’ critical processes use Statesman, and by the time I left we had transition tables with well over 10B rows. It became such an essential tool that I’d argue it was a powerful competitive advantage. Statesman is even reflected externally, such as in the GoCardless public API with endpoints providing rich audit trails.