Build1 distinct publisher2 min readUpdated
Putting the job queue in the customer database costs no new infrastructure and hands autovacuum a race it loses. The benchmark cited against it caps Postgres near 660 messages a second.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The unit of accounting here is the dead tuple. Claiming a job is an update, completing it is an update, retrying it is another, and Postgres writes a new row version for each one [2]. That makes the jobs table the highest-churn object in a schema whose other tables are mostly read. At the ceiling the cited benchmark reports, about 660 messages a second [5], even a minimal two updates per job puts roughly 1,320 dead row versions a second in front of autovacuum [3]. Gunnar Morling's argument, in his November 3, 2025 piece, is that vacuum eventually loses that race and the WAL piles up behind it [4]. Brandur Leach, formerly a staff engineer at Stripe, describes the same end state as table bloat, index fragmentation and autovacuum starved of room [3]. The vacuum budget and the WAL are not queue resources. They are the customer's.
The throughput gap is the headline number, and it is the less interesting one. RabbitMQ moved 25,000 messages a second in the same test environment [6], about 38 times as much [1]. The comparison worth sitting with is FIFO SQS, the deliberately capped managed option at 3,000 messages a second [8]: still roughly four and a half times the Postgres figure [2]. The complexity being avoided is a queue URL.
Recovery is where the shared substrate actually bills you. AWS engineers described the loop in a December 17, 2021 Architecture Blog post: a stalled delivery process pushes backpressure onto the database, which produces more failed work [9]. A broker backlog is drained by adding consumers. A bloated jobs table is drained by vacuum, which needs the write rate to fall, which needs the workers to back off, which is the opposite of what a retry loop does. Meanwhile every worker node holds a connection, and Postgres forks an OS process per connection, so polling workers churn through the pool that user-facing queries are drawing from [10].
The evidence for the throughput half of this case is thin: one benchmark, one date, one payload size, 38ms at P95 [5], with no methodology quoted. Hardware and batching would move that figure a long way. The coupling half needs no benchmark, and the article's own carve-out is the useful sentence in it: sporadic background work at low rates is fine, and the failure is assuming that behaviour survives production volume [11]. So the threshold is a metric, not an architecture. Watch dead tuples and vacuum lag on the jobs table against the rest of the schema, and answer the question the piece poses directly, which is whether your database goes down when your queue does [12].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
SELECT ... FOR UPDATE SKIP LOCKED lets a team reserve jobs with zero new infrastructure: no brokers, no ops, one line of code, hidden inside the most critical component.
Postgres MVCC creates a new row version for every update, and a queue is a table that is repeatedly modified: claiming a job updates it, completing it updates it, retrying it updates it again.
Postgres creates a new OS process for each connection, and many worker nodes constantly polling, claiming and updating jobs cause continuous connection churn that can deplete the pool, making user-facing queries compete with job runners.
The author does not rule the pattern out: Postgres queues are fine for minor internal tasks or a sporadic background job at low job rates, and the failure is assuming that what works at low volume works at scale with production traffic.
A benchmark on May 15, 2023 indicated Postgres-as-a-queue maxed out at approximately 660 messages per second with a 1KB payload and a 38ms P95 publish latency.
The author's reality check: if your database would go down when your queue does, you did not build a shortcut, you built a single point of failure.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Thin and mostly secondhand
One first-person opinion post is the entire cluster. Its uncontroversial mechanical claims (MVCC row versioning per update, process-per-connection) are internally coherent, but every quantitative or authoritative element is a restatement: an unattributed and unlinked May 15, 2023 benchmark, two practitioner analyses summarized without quotation, an AWS blog warning cited by date only, and SQS quotas with no documentation reference. Nothing in the cluster lets a reader verify the numbers or reproduce the failure.
No usage or deployment data
The post asserts the pattern is popular ('nowadays individuals place their message queue directly into the database used by their customers') but supplies no deployment counts, user disclosures, library download or install figures, or named teams on either side of the choice. The single benchmark reference measures throughput, not adoption, so no adoption level can be scored without guessing.
Overstated relative to supplied evidence
The framing — a SPOF you'll regret at 3am, a 'nearly 40 times' throughput gap, vacuum losing a race it cannot win — is considerably stronger than what the cluster proves. The central multiple derives from one unattributed three-year-old benchmark, and the combined queue-plus-database outage is argued rather than documented with any incident. The gap is moderate rather than severe because the underlying mechanisms (MVCC churn, process-per-connection contention) are described accurately and the author volunteers a genuine low-volume exception instead of a blanket prohibition.
Engagement-shaped personal post, no disclosed vendor tie
This is an individual practitioner post on a community publishing platform, written in provocative counter-consensus style ('Just use Postgres' as hype gone wrong) and closing with a discussion prompt asking readers for their rule of thumb — a structure that rewards reach and argument over verification. No sponsorship, employer, vendor affiliation or commercial interest in brokers or managed queues is disclosed anywhere in the supplied material, so there is no evidence of a direct commercial incentive; the measurable pressure is attention rather than sales.
Low
Direction of the argument is plausible and the mechanisms are correctly named, but confidence is limited by a single-publisher cluster, no corroboration for any external citation, a three-year-old unattributed benchmark carrying the quantitative weight, and a complete absence of adoption or incident data. Enough to treat as a design caution, not enough to treat any specific number as established.
build
Three services you can delete: queue, cache and search in one Postgres1 distinct publisher
build
Four control planes, one Postgres: a team's case against polyglot persistence1 distinct publisher
build
The middle tier for Postgres: own kernel, no public IP, and you own the backups1 distinct publisher
build
Cloud waste is a tagging habit, and that 76% shutdown number needs a second look1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 22, 2026