

Discussion summary
PostgreSQL transactions are viewed as powerful tools for distributed systems, with some discussing their use as a state store and the importance of co-locating checkpoints. Opinions vary on reliability and best practices.
What the discussion says
- Postgres can serve as a distributed state store with proper wrapping.
- Co-locating checkpoints with writes prevents half-committed states.
- Relying solely on Postgres means system downtime affects everything.
- Some suggest using additional tools alongside Postgres for resilience.
- There is debate on whether Postgres alone can handle distributed application state.
“This is the trick that kills the dual-write bug in money-movement systems.”
“Just start writing stored functions already.”
Comments
Hacker News
by valentynkit
by hoppp
by est
It seems this article is trending toward that view: If you can maintain transactional consistency along with application workflow state, then would this generalize to maintaining distributed application state in general?
The follow-up would be: Would this be preferable to Valkey/Redis?
by evilturnip
Yes, in the sense of 'too good to be true'
by mrkeen
As to which technical solution would be optimal there are a bunch of factors to consider and I think preferences around features could lead you to a variety of options. Postgres is excellent as long as you're minimizing the amount of data piping directly through it or operating at a reasonable scale.
by munk-a
by cadamsdotcom
by nickpeterson
In the OP's case, pg down but luckily workflow works??
by est
Suppose you use PostgreSQL + Something Else instead of Just PostgreSQL, and PostgreSQL goes down: Is anything still working?
I suspect the answer is "Very little still works when the DB is down", so the opportunity cost of Just PostgreSQL is low.
Also, while it's possible that PostgreSQL still has concurrency bugs, I think for most teams the odds of hitting a concurrency bug in PostgreSQL are much lower than the odds of hitting a concurrency bug in your own complicated bespoke in-house distributed system.
by akoboldfrying
I have rolled my own little durable workflows in Postgres before, in fact before I even knew durable workflows were a thing with solutions like Temporal. That's fine for many cases where you aren't doing enough steps for it to be tedious, and/or you want permanent records. Would do it again, but not for atomicity reasons.
Other comments have already discussed the issue with the outbox UDF, your external system has to poll and retry either way. It works though. Maybe I'm misunderstanding this?
by zadikian
by KraftyOne
by bsaul
by KraftyOne
This sounds a lot like reinventing a message queue. Someone trying this in the future might learn painful lessons about ordering, commits, partitioning, dead-letter-queues, replayability, don't-call-me-I'll-call-you, and anything else a Kafka-like comes with out of the box.
by mrkeen
by zyngaro
Something like Restate actually implements distributed transactions.
by lima
by JackSlateur
by aynyc
When workers query the db for jobs the rows get locked by the select and there are no race conditions or duplicate assigned jobs
by hoppp
Here's another blog post about how a Postgres-backed task queue can run at scale: https://www.dbos.dev/blog/making-postgres-queues-scale
by KraftyOne
by Crowberry
Is it really a distributed system or just a bunch of services with a central database?
by cloudie78
I've asked myself this question every single time I've had to use Zookeeper.
Apache Kafka being the poster child of the problem, with HBase in a close second.
by gopalv
*: edit, maybe a better example here is a rail system with a single central dispatcher is centralized but may still be distributed
by tomjakubowski
There will always be a window for potential loss due to solar flares/whatever but the key in designing a system like this is to make sure you're aware of how the system can fail, accept that outcome and then work to, as much as possible, shrink the distance in cycles/logic between each persistence committal. Logic should be front-loaded to do as much prep work as possible before any irreversible actions happen and then those irreversible actions should be ordered to your preference and dispatched as quickly and cheaply as possible in a safe manner.
by munk-a
In most services, I often swap out the message broker or the workflow engine, but the database almost always stays the same.
I'm not sure if I've understood this correctly.
by jdw64
by KraftyOne
One of the technical questions was "if you have a db and a message queue, how do you get your update to alter both or neither (i.e. transactionally)"?
I thought about it for a couple of minutes, then came back with something like "I can't, and you can't either." Then I proposed the usual spiel about using a replicated-state-machine/write-ahead-log/event-sourcing (whatever it might be called at the time) and leaning into eventual consistency as the only practical solution.
He asked if I'd heard about the outbox pattern, so I let him describe it. Sure enough it sounded like this article. The secret to transacting across the database D and the message queue Q:
(D,Q)
is to split D into two parts (the State and the Outbox), transact across those instead (S,O) Q
and then just pretend that you have a transaction across D and Q.by mrkeen
by game_the0ry
Join the discussion
Write your take first — we'll ask for email only when you're ready to publish.
- Hacker News
- This is the trick that kills the dual-write bug in money-movement systems: co-locate the checkpoint with the write so a mid-workflow crach can't leave you half-commited.by valentynkit
- Just start writing stored functions already.by hoppp
- and triggers!by est
- Can you use postgres as a state store for a distributed application?
It seems this article is trending toward that view: If you can maintain transactional consistency along with application workflow state, then would this generalize to maintaining distributed application state in general?
The follow-up would be: Would this be preferable to Valkey/Redis?
by evilturnip - > then would this generalize to maintaining distributed application state in general?
Yes, in the sense of 'too good to be true'
by mrkeen - Yes you can - usually I think it's advisable to wrap postgres in a shim application to provide a consistently defined surface you can control but postgres can absolutely serve as the authority node on data correctness.
As to which technical solution would be optimal there are a bunch of factors to consider and I think preferences around features could lead you to a variety of options. Postgres is excellent as long as you're minimizing the amount of data piping directly through it or operating at a reasonable scale.
by munk-a - The coolest thing about using Postgres for everything is when the database works everything works and when the database goes down it all goes down, so you get to fix nothing most days then everything all at once.by cadamsdotcom
- Only a Sith deals in absolutesby nickpeterson
- > when the database goes down it all goes down
In the OP's case, pg down but luckily workflow works??
by est - > when the database goes down it all goes down
Suppose you use PostgreSQL + Something Else instead of Just PostgreSQL, and PostgreSQL goes down: Is anything still working?
I suspect the answer is "Very little still works when the DB is down", so the opportunity cost of Just PostgreSQL is low.
Also, while it's possible that PostgreSQL still has concurrency bugs, I think for most teams the odds of hitting a concurrency bug in PostgreSQL are much lower than the odds of hitting a concurrency bug in your own complicated bespoke in-house distributed system.
by akoboldfrying - The part about durable workflows is technically correct, but it's focusing on different things than what I've ever run into in practice. Any mildly complex system will have side effects outside your DB, then you want idempotency. If you have no side effects, you probably don't need a durable workflow in the first place? Maybe there's a more concrete example.
I have rolled my own little durable workflows in Postgres before, in fact before I even knew durable workflows were a thing with solutions like Temporal. That's fine for many cases where you aren't doing enough steps for it to be tedious, and/or you want permanent records. Would do it again, but not for atomicity reasons.
Other comments have already discussed the issue with the outbox UDF, your external system has to poll and retry either way. It works though. Maybe I'm misunderstanding this?
by zadikian - You still need idempotency for side effects outside your database, that's true (and fundamental to durability). But now you get exactly-once semantics for operations on your database, which can be quite valuable if your workflow performs many such updates or they're particularly complicated or stateful.by KraftyOne
- i don't understand the last point of UDF. Either you need the state to be updated atomically across different systems or you don't. But writing a row in a system in order to update the second one at any random time in the future isn't really much different from enqueuing a job in queue.by bsaul
- The key is that the UDF's enqueue is transactional with the database update. Let's say the database update is inserting a new order. This provides the guarantee that if a new order is inserted, a job to process the order is also enqueued. It's impossible for a new order to be inserted without its processing job also being enqueued. Then the durable workflow/queue system is responsible for making sure the processing job, once enqueued, actually executes.by KraftyOne
- Your intuition sounds right to me.
This sounds a lot like reinventing a message queue. Someone trying this in the future might learn painful lessons about ordering, commits, partitioning, dead-letter-queues, replayability, don't-call-me-I'll-call-you, and anything else a Kafka-like comes with out of the box.
by mrkeen - The article is ridden with misconception. Have you guys ever heard of the CAP theorem ? Disturbed system suck let's implement a non distributed one. The title is also misleading: Postgres transactions are not distributed.by zyngaro
- This. It's easy to forget that Postgres is fundamentally a single-node database without distributed transactions. It won't pass the Jepsen test suite with multiple nodes. DBOS, Temporal and friends inherit this limitation.
Something like Restate actually implements distributed transactions.
by lima - Are they not ?by JackSlateur
- OK. I've read it a few times and still don't understand. Where is the distributed part? You store data in a single transaction into postgres. What/who is notifying the message queue?by aynyc
- I've been writing distributed workers for ages with stored functions that have a SELECT FOR UPDATE query.
When workers query the db for jobs the rows get locked by the select and there are no race conditions or duplicate assigned jobs
by hoppp - You build a distributed system on top of this! For example, you may have many distributed workers durably executing workflows from the Postgres-backed task queue. The Postgres transactions allow you to atomically perform operations spanning both your task queue and your business data.
Here's another blog post about how a Postgres-backed task queue can run at scale: https://www.dbos.dev/blog/making-postgres-queues-scale
by KraftyOne - We’ve got an in-house pubsub solution that lives in the main applications database, so pretty much exactly as described in the article. And the atomicity it allows is indeed really nice!by Crowberry
- Congratulations, you discovered a mutex.
Is it really a distributed system or just a bunch of services with a central database?
by cloudie78 - > Is it really a distributed system or just a bunch of services with a central database?
I've asked myself this question every single time I've had to use Zookeeper.
Apache Kafka being the poster child of the problem, with HBase in a close second.
by gopalv - I don't think it's true that distributed and decentralized mean the same thing. A hub and spoke rail system is centralized, but it's still a distributed system, if it has multiple trains running concurrently.* A distributed system has to coordinate somehow, and a single central DB is one way of doing it.
*: edit, maybe a better example here is a rail system with a single central dispatcher is centralized but may still be distributed
by tomjakubowski - We've leveraged the atomicity of transactions with a fail-safe approach for external service interactions for client email sending. This could certainly be done with a formal queue though it'd operate very similarly and achieve the same guarantees as we have today (and was built when we were too small to justify such an infra spend). Internally we have jobs that execute complex logic to transform data from a pending state to a computed state which lean on the DB's atomicity to guarantee that data is successfully transitions and those tasks are all incredibly resilient - but when a secondary persistence store is involved transactional guarantees need to be compromised in some manner. In our email sending example we have the opinion that it is more important to guarantee a client receives all notifications compared to a notification being guaranteed to be sent precisely once so our mechanism in sending is to confirm email sending was successful and then close a transaction that removes that message from the pending list.
There will always be a window for potential loss due to solar flares/whatever but the key in designing a system like this is to make sure you're aware of how the system can fail, accept that outcome and then work to, as much as possible, shrink the distance in cycles/logic between each persistence committal. Logic should be front-loaded to do as much prep work as possible before any irreversible actions happen and then those irreversible actions should be ordered to your preference and dispatched as quickly and cheaply as possible in a safe manner.
by munk-a - So my understanding is that they're aligning the workflow progression unit and the database commit unit on a one-to-one basis. In other words, each step in the workflow becomes a database commit unit. That's why the outbox pattern gets simplified. But in exchange, the database itself becomes tightly coupled to the workflow, which will make it architecturally difficult to separate later on. Although, to be fair, I almost never actually need to separate the database anyway.
In most services, I often swap out the message broker or the workflow engine, but the database almost always stays the same.
I'm not sure if I've understood this correctly.
by jdw64 - Yes, the core design is building a workflow system on a database--essentially, replacing the central orchestrator most workflow systems use with a Postgres database. This previous blog post goes into more detail: https://www.dbos.dev/blog/postgres-is-all-you-need-for-durab... (HN discussion: https://news.ycombinator.com/item?id=48313530)by KraftyOne
- I walked away from a job interview a few years ago on this point.
One of the technical questions was "if you have a db and a message queue, how do you get your update to alter both or neither (i.e. transactionally)"?
I thought about it for a couple of minutes, then came back with something like "I can't, and you can't either." Then I proposed the usual spiel about using a replicated-state-machine/write-ahead-log/event-sourcing (whatever it might be called at the time) and leaning into eventual consistency as the only practical solution.
He asked if I'd heard about the outbox pattern, so I let him describe it. Sure enough it sounded like this article. The secret to transacting across the database D and the message queue Q:
is to split D into two parts (the State and the Outbox), transact across those instead(D,Q)
and then just pretend that you have a transaction across D and Q.(S,O) Qby mrkeen - I envy you DB + distributed systems specialists. Reminds me I still have a lot to learn.by game_the0ry
Related stories
Why we built yet another Postgres connection pooler
pgdog.dev · 187 points · 44 comments
Cloudflare Meerkat - Globally distributed consensus
blog.cloudflare.com · 69 points · 8 comments
Decoding the obfuscated bash script on a Uniqlo t-shirt
tris.sherliker.net · 1072 points · 181 comments
StreetComplete: Fixing OpenStreetMap, one tiny quest at a time
streetcomplete.app · 761 points · 182 comments
Every new car sold in the European Union must include a driver monitoring camera
allaboutcookies.org · 737 points · 969 comments
Chat Control 1.0 and 2.0 Explained
fightchatcontrol.eu · 645 points · 238 comments