Keeping a Postgres queue healthy
Apr 10, 2026Simeon Griggs

Summary
This post details how job queue workloads, characterized by high insert/delete churn, can lead to performance degradation and table bloat in Postgres due to the accumulation of dead tuples. It explains the mechanics of MVCC, dead tuples, and how autovacuum struggles to keep up when write churn outpaces cleanup or when transactions hold locks. The post uses a concrete example of a job queue table and worker process to illustrate how `DELETE` operations mark rows as dead, which are then scanned by both heap and index traversals, incurring overhead. It emphasizes that the problem is not just throughput but also the visibility of dead tuples to active transactions and the impact of competing workloads (like OLAP) on autovacuum's effectiveness.