What is table bloat in PostgreSQL and how do you fix it?

Answer

Table bloat occurs when dead tuples (from updates and deletes) accumulate faster than VACUUM can reclaim them, causing the table's physical size to grow far beyond its live data size. This wastes disk space and degrades sequential scan performance. Measure bloat: use the pgstattuple extension (SELECT * FROM pgstattuple('tablename');) or queries against pg_class. Causes: high UPDATE/DELETE volume, insufficient autovacuum frequency, long-running transactions preventing dead tuple removal. Fixes: (1) Tune autovacuum aggressiveness per table. (2) VACUUM FULL tablename — rewrites the table compactly but requires an exclusive lock (use in maintenance windows). (3) pg_repack extension — rewrites tables online without an exclusive lock. (4) Partition large tables to vacuum partitions independently. Index bloat is separate — use REINDEX CONCURRENTLY.