Hi HN, I’m jumski. I spent last year building pgflow – a workflow orchestration engine built entirely on Supabase primitives (Postgres, Queues, Edge Functions, Realtime).
How This Started
I was transitioning to Supabase and building a personal app with multi-step LLM pipelines. I needed these to trigger from DB changes, cron, and the browser – but every workflow solution required external services.
From my Sidekiq experience, I knew that having each step handler send the next message to the queue shouldn’t be part of business logic – it’s error-prone and scattered. I realized I could move all orchestration to SQL – let the database decide what runs next while handlers focus purely on their task. To make this work on Supabase without external services, I created a self-respawning worker on Edge Functions to bypass time limits.
The Problem
Building workflows on Supabase today means manually wiring pg_cron schedules, pgmq queues, Edge Functions, and state tables. For a simple article processing workflow (fetch → parallel summarize + extract → publish), you’re writing ~240 lines across 3 queue setups, 3 Edge Functions, 3 cron schedules. Tedious boilerplate.
What pgflow Does
Same workflow, 20 lines:
new Flow({ slug: 'article_flow' })
.step({ slug: 'fetchArticle' },
(input) => scrapeUrl(input.run.url))
.step({ slug: 'summarize', dependsOn: ['fetchArticle'] },
(input) => summarize(input.fetchArticle))
.step({ slug: 'extractKeywords', dependsOn: ['fetchArticle'] },
(input) => extractKeywords(input.fetchArticle))
.step({ slug: 'publish', dependsOn: ['summarize', 'extractKeywords'] },
(input) => publishArticle(input.summarize, input.extractKeywords));
Flow inputs and outputs are fully type-inferred – your IDE autocompletes dependencies and catches errors at compile time. The only type annotation needed is the flow input.
You write workflows in TypeScript, compile them to SQL inserts that define your graph structure, and pgflow handles everything else. Postgres IS the orchestrator – managing a DAG of state machines, using pgmq to distribute tasks to workers. All state changes are fully transactional.
vs Alternatives
Unlike DBOS which uses decorators on imperative code, you explicitly define your DAG upfront. Unlike Trigger.dev/Inngest, everything lives in your existing Supabase project. You can query workflow state directly with SQL, and start flows from DB triggers or pg_cron.
Try It
– Demo: https://demo.pgflow.dev (paste any article URL)
– Docs: https://pgflow.dev
– GitHub: https://github.com/pgflow-dev/pgflow
Status: Beta – teams are using it in production. Fully open source, Apache 2.0 licensed.
Questions for HN:
What Supabase automations are you currently duct-taping together?
What’s stopping you from using existing workflow tools?
Also curious: is SQL-based orchestration taking the “everything in the database” philosophy one step too far?
Comments URL: https://news.ycombinator.com/item?id=45899152
Points: 1
# Comments: 0
Source: demo.pgflow.dev