apps/www/_blog/2024-12-10-durable-workflows-in-postgres-dbos.mdx
Michael Stonebraker is the inventor of Postgres and a Turing Award winner. His latest venture is DBOS, a three-year joint research project between Stanford and MIT. The DBOS team have built a Durable Workflow engine using Postgres. It's one of the more elegant designs I've seen, leveraging the features of Postgres to keep it lightweight and fast.
The DBOS team have released a Supabase integration, so you can use your Postgres database as a durable workflow engine.
Continue reading or just get started?
I really love the design of DBOS, so I'm going to write more below. Their design is aligned with our philosophy at Supabase: “just use Postgres”. I'll take you through the lower-level details in the rest of this post. If you just want to get started using DBOS with Supabase, get started using their tutorial:
Let's start with a common situation where a workflow is useful: you're running an e-commerce platform where an order goes through multiple “steps”:
The process is simple, but writing a robust program for this is surprisingly difficult. Some potential problems:
A Durable Workflow Engine helps with these problems (and more). There are a few on the market that provide different architectures like Oban, Trigger.dev, Inngest, Windmill, Temporal, and AWS Step Functions.
DBOS offers a relatively unique approach to Workflows, storing the state in your own Postgres database. Let's explore how DBOS does it.
DBOS is a platform where you can write your programming logic in serverless functions (similar to Supabase Edge Functions). Functions can be written in either Python or TypeScript.
One thing that's different to Supabase Edge Functions is the ability to add decorators to your Functions with DBOS.step() and DBOS.workflow():
When you do this, DBOS stores the “state” of every step in Postgres:
This is the part I find the most interesting! If you're a gamer, it's a bit like having a “save point” in your programs. If a Function fails at any point, a new Function can start, picking up at the last checkpoint.
When you create an application with DBOS, they create a new database inside your Postgres cluster for storing this state.
Using their “Widget Store” example, you can see two new databases -
widget_store: for storing the application datawidget_store_dbos_sys: for storing the workflow state.The widget_store_dbos_sys database holds the workflow state:
The DBOS team were kind enough to share some of the logic with me about how their workflow engine works:
workflow_status table with a PENDING status. It also stores its inputs in Postgres.operation_outputs table.workflow_status table to SUCCESS (or to ERROR, if it threw an uncaught exception).If a program is interrupted, on restart the DBOS library launches a background thread that resumes all incomplete workflows from the last completed step.
PENDING workflows, then starts each one. Because workflows are just Python functions, it can restart a workflow by simply calling the workflow function with its original inputs, retrieved from Postgres.All this works because workflows are deterministic, so they can re-execute them using stored step outputs to recover their pre-interruption state.
DBOS isn't the first to create a workflow engine. Others in the market include Temporal and AWS Step Functions. DBOS provides a number of benefits over workflow engines that use external orchestrators like AWS Step Functions:
Because a step transition is just a Postgres write (~1ms) versus an async dispatch from an external orchestrator (~100ms), it means DBOS is 25x faster than AWS Step Functions:
DBOS has a special @DBOS.Transaction decorator. This runs the entire step inside a Postgres transaction. This guarantees exactly-once execution for databases transactional steps.
You can set an idempotency key for a workflow to guarantee it executes only once, even if called multiple times with that key. Under the hood, this works by setting the workflow's unique ID to your idempotency key.
Since it's all in Postgres, you get all the tooling you're familiar with. Backups, GUIs, CLI tools - you name it. It all “just works”.
To get started with DBOS and Supabase, check out their official integration docs: