Microsoft Just Put a Workflow Engine Inside Postgres
Disclosure: This post was researched, drafted, and edited with AI assistance. Microsoft's pg_durable GitHub repository and README were the primary source; the HN announcement thread (281 points, 72 comments at time of writing) was the secondary source. Opinions, framing, and analysis are the author's.
Microsoft open-sourced pg_durable on June 5th and most coverage will focus on the SQL DSL, the ~> and |=> operators, and the question of whether writing workflows as SQL strings is a good idea. That's the wrong story. The real story is that the author of pg_durable is the same person who built the orchestration layer for Durable Task Framework — the framework that has been running Microsoft-internal workflows and Azure Durable Entities for close to a decade — and the team is now putting that capability inside Postgres. If you've ever told someone "we need a workflow engine for this," and the answer was Temporal, or Airflow, or Step Functions, that answer just got weaker.
What pg_durable actually does
A pg_durable function is a graph of SQL steps that Postgres executes and checkpoints as it goes. If the database crashes, restarts, or a step fails, execution resumes from the last durable checkpoint instead of forcing you to reconstruct state by hand. You start one with a one-liner:
SELECT df.start(
'SELECT id FROM documents WHERE processed = false LIMIT 100' |=>
'batch' ~>
'UPDATE documents SET processed = true WHERE id = ANY($batch)'
);
The runtime checkpoints between steps, so a restart in the middle of a long job doesn't rerun work that already succeeded. Status and results are queryable from standard Postgres tables (the README points to df.instances) — same auth model, same backup model, same observability tooling. There is no Redis, no Temporal cluster, no separate queue service. It installs as a PostgreSQL extension and ships as a Debian package for PG 17 and 18 on amd64.
Under the hood, pg_durable is built on duroxide, a Rust-based durable execution runtime that handles deterministic replay, checkpoints, sub-orchestrations, and timers. pg_durable is the Postgres-flavored wrapper (PostgreSQL License); duroxide is the engine (MIT). The two components carry different licenses.
The "Postgres is enough" thesis just got real
There's been a persistent argument in the Postgres community for years — most visibly at postgresisenough.dev — that you can replace a lot of operational machinery with Postgres if you reach for the right extensions. pg_durable is the most ambitious version of that argument yet: it claims that durable execution, the thing that has historically required a separate orchestrator like Temporal, is just another primitive the database should provide.
The README's own list of "what you're probably doing today" makes the displacement target explicit:
pg_cronplus a jobs table, status columns, retry counters, and a polling worker- An external orchestrator (Airflow, Temporal, Step Functions, Argo) calling back into Postgres
- A queue plus workers plus a separate state table to coordinate retries
- A plpgsql procedure that works until a crash or long-running transaction forces you to start over
That's the menu. If pg_durable works as advertised, several of those menu items become the same thing, and the "we need Temporal for this" justification gets harder to make.
The maintainer of postgresisenough.dev is already asking for a PR to add pg_durable to the site. That's the tell — the people who've been arguing "Postgres is enough" see this as a real entry in the catalog, not a marketing stunt.
The Microsoft stake is bigger than it looks
Two things are easy to miss. First, the lead committer, affandar, is also the author of Durable Task Framework, the orchestration library that has powered Azure Durable Functions and Durable Entities. This isn't a new team learning the durable-execution category. It's the same team shipping their next move in the open.
Second, the same repo's documentation points at Azure HorizonDB, Microsoft's new PostgreSQL cloud service, as the place to try pg_durable — and notes that it's "engineered for performance and built with pg_durable inside." This isn't a one-off OSS contribution. It's a positioning move. Microsoft is betting that the database is the right substrate for workflow orchestration, and the database they want to bet on is Postgres, not a proprietary service they control end-to-end. That tells you something about where they think the leverage is.
The honest counterargument: the SQL DSL is awkward
The most consistent pushback in the HN thread is that the workflow syntax is hard to read. One commenter, looking at the README example, called it "bizarre." Another pointed out that embedding SQL strings inside other SQL strings — which is what the df.start(...) syntax essentially is — is a maintainability hazard waiting to happen.
Both criticisms are fair, and the maintainers know it. gdecandia, a contributor, said: "Agree that the DSL ergonomics can be improved. Our pipelines use a higher level language and therefore simplified, but pg_durable is meant to solve a wider array of problems. We're happy to take suggestions for improvements." A committer also noted that the state-provider layer is an extensibility point — they're open to alternative backends like a pgmq-based state provider, rather than the default PostgreSQL one.
The DSL awkwardness is the price you pay for putting workflows inside a SQL-shaped runtime. The tradeoff is real: pure SQL workflows are more constrained than Temporal's TypeScript SDK, but they force the architecture into a shape that survives database restarts, which is the whole point. If you've been writing Temporal workflows in TypeScript and never worrying about the underlying state store, you may not feel the pain pg_durable is solving. If you've been writing plpgsql procedures and losing work to transaction timeouts, you will.
What it's not
- It's not a replacement for Airflow if your workflows fan out across heterogeneous systems (S3 + Spark + Slack + a database). The README explicitly says: "if the workflow mostly lives outside Postgres and spans many heterogeneous systems," reach for a general-purpose orchestrator.
- It's not a sub-millisecond request handler. It's for durable background work, not synchronous request paths.
- It's not available everywhere. The first-class deployment is Azure HorizonDB. If you're on AWS RDS, Aurora, Supabase, or Neon, you'll need to install the extension yourself and check whether your provider's PG build allows it.
- It's not the first durable-execution project on Postgres. pg-boss, pg-workflows, and several others have been filling this niche for years. pg_durable is the most ambitious and the first with a major-vendor seal.
The performance and architecture story that's still developing
The README lists workloads (vector embedding pipelines, ingest pipelines, scheduled maintenance, fan-out aggregation, external API workflows) but doesn't publish benchmark numbers as of the v0.2.2 release. That's reasonable for an early OSS drop, but it means the "is this faster than my current setup" question is one you'll have to answer with your own load tests. The engine is Rust (duroxide) and the integration is in-PG, so there's no obvious reason it should be slow — but the early numbers will tell.
The architectural claim most worth testing is the parallel-fanout story. The README says pg_durable supports "fan-out aggregation: run independent queries in parallel, then join the results." If this works inside a single Postgres connection without an external worker pool, it's a real differentiator from the queue-plus-workers pattern.
The original take: the orchestrator is being absorbed into the database
pg_durable doesn't beat Temporal feature-for-feature today — Temporal has sub-orchestrations, versioning, signals, queries, and a TypeScript SDK that a generation of developers have already learned. pg_durable has none of those. The interesting question is what happens if a category of workflow tools gets pulled into the database itself over the next three to five years. Microsoft shipping pg_durable as a PG extension, embedded in their new cloud Postgres, is a strong signal that the answer to "where does the orchestrator live?" is shifting from "separate service" back to "the database." If this pattern holds, expect to see competing extensions in MySQL, MariaDB, and DuckDB within 24 months. The durable-execution category as a standalone product category gets thinner with each one.
The counter-trend is the continued rise of general-purpose orchestrators with mature SDKs (Temporal, Restate, Inngest) and the assumption that workflows will increasingly be written in application code, not SQL. If you're betting on that future, pg_durable is a 2026 data point, not a trend reversal. If you're betting on the database-absorbs-orchestration future, this is the most significant open-source release of the year so far.
What to do this week
# Check what your current workflow stack actually is
SELECT count(*) FROM information_schema.tables
WHERE table_name IN ('jobs', 'job_runs', 'workflow_state', 'scheduled_tasks');
# If you have more than 2 of these, you have a homegrown orchestrator.
# Look at what extensions your Postgres allows
SELECT name, default_version, installed_version
FROM pg_available_extensions
WHERE name IN ('pg_cron', 'pg_durable', 'pgmq');
# If pg_durable shows up with a version, your provider has built it in.
# If it doesn't, ask them when it will.
If you have a Temporal deployment that's mostly doing "fetch some rows, update some rows, wait, update some more rows" — that's exactly the workload pg_durable is for, and it's worth a one-week prototype to see if you can drop the orchestrator from your architecture diagram.
If you're on Azure and you've been waiting for "modern" Postgres features to land on Azure, the HN commenter who said "I'm trapped on Azure" is the user you should be listening to. Azure HorizonDB is the response to that complaint, and pg_durable is one of the first things it ships with.
If you're a maintainer of an existing pg-boss or pg-workflows-style project: now is the time to make sure your README has a "how this compares to pg_durable" section. The displacement question is going to come up in every HN thread for the next quarter.
What this means for you
The story of pg_durable is that the most valuable open-source workflow orchestration capability — the kind that was, until now, the reason to deploy a separate service — is now an install command away from every team that already runs Postgres. The deployment cost of "I need durable execution" just went from "spin up a cluster" to "apt install pg-durable-postgresql-17." That's the same kind of leverage shift that Redis 8.8's array data type brought to in-memory data structures, and the same pattern Cloudflare applied in acquiring VoidZero — own the substrate, and the layers above it become someone else's problem to defend. (For more on what "owning the substrate" looks like on the model side, see how Gemma 4 12B dropped the multimodal encoder — different substrate, same play.)
The next time someone tells you "we need Temporal for this," the better question is: do you need a workflow engine, or do you need Postgres to remember what it was doing?

No comments:
Post a Comment