At 3 am the pager is activated. Your queue is backed up, your database is on fire, and those two facts are the same fact. This is the trap nobody warns you about when they advise you to simply utilize Postgres for all your needs.
The hype has a new victim
The simple advice, "Just use Postgres" was very effective in the beginning. You didn't need a complex architecture involving six different services. It was enough to deploy the common monolith and you could rest at night. After that, the hype got out of control. Nowadays, individuals place their message queue directly into the database used by their customers. I see why people find it attractive. SELECT ... FOR UPDATE SKIP LOCKED allows you to reserve jobs with zero new infrastructure. No brokers, no ops, just one line of code. You just hid it inside your most critical, least replaceable component.
MVCC was not built for this
The downside you may encounter later on is that Postgres creates a new row for every update, but that's the nature of MVCC.
A queue can be likened to a table that you keep modifying. You claim a job, then modify the table.
Complete a job, again, modify the table. Retrying the job, once more, update the table.
Brandur Leach who used to be a Staff Engineer with Stripe, recently detailed this in his article "Transactionally Staged Job Drains in Postgres" . The result: table bloat, index fragmentation, autovacuum starved for air.
Gunnar Morling argued the same in his analysis from November 3, 2025, "'You Don't Need Kafka, Just Use Postgres' Considered Harmful": long-running consumer transactions will at some point inevitably lead to MVCC bloat and WAL pile-up, and vacuum just loses the race against the change rate.
Your queue is slowly damaging the database where it is stored.
The numbers are not close
I want to bring up throughput because this is the bottleneck in our fantasy.
On May 15, 2023, a benchmark indicated that Postgres-as-a-queue maxed out at approximately 660 messages per second using a 1KB payload, with a 38ms P95 publish latency.
RabbitMQ processed 25,000 messages per second in the same test environment. It was not twice as much, not three times as much, but nearly 40 times as much.
The managed options available are excessive. Regular Amazon SQS will provide high throughput almost without limit.
And if you need something more, FIFO SQS will achieve exactly-once processing with a ceiling of 3k messages per second or 30k in a batch.
You are opting for a tool that maxes out at 660 to steer clear of "complexity." Meanwhile, the dull cloud queue is scaling above and beyond you.
The SPOF nobody planned for
Now the 3am part. Everything is fine until your delivery process stalls.
AWS engineers actually sounded the alarm on this in a December 17, 2021 Architecture Blog post; an inoperable delivery process places backpressure on the database, which creates a feedback loop that results in even more failed work.
I'm sorry, could you please read that again? The queue failure and the database failure merge into a single event.
→ Your queue is down, so your app is down. → Your database is thrashing, so your queue can't recover. → Every worker retry makes both worse.
There is also a silent killer. For each connection, Postgres creates a new OS process.
Many worker nodes are constantly polling, claiming, and updating jobs. This results in continuous connection churn, which can deplete your pool, causing your user-facing queries to compete with the job runners for a spot.
A single point of failure was created by you, which was responsible for handling two tasks.
When it's actually fine
I'm not ruling it out completely. For minor internal tasks within the system or a sporadic background job, I guess it's okay. I think Postgres queues are amazing if you're not doing a ton of jobs per minute and you don't mind not having a broker. SKIP LOCKED is a beautiful thing. The issue arises when you assume that something that "works at low volume" will also "work at scale with production traffic." These are two separate assumptions, and the pager exists in the space between them. Here's a simple reality check. Would your database go down if your queue did? Then, you didn't create a shortcut; you built a SPOF. Well, if you have boring stuff, it might be the right time to offload it, right? What's your rule of thumb, when does "just use Postgres" cease to be common sense and become a problem you'll struggle to solve?
Top comments (0)