# When should i use postgres vacuum full instead of truncate?

l0t.me · November 9, 2026

> understanding vacuum full mechanics PostgreSQL manages transaction ID wraparound through autovacuum, which freezes old transaction IDs to prevent...

## understanding vacuum full mechanics

PostgreSQL manages transaction ID wraparound through autovacuum, which freezes old transaction IDs to prevent catalog corruption. When tables accumulate significant dead tuples, the database grows bloated, slowing queries due to unnecessary I/O. Vacuum full rewrites the entire table physically, reclaiming disk space immediately rather than marking it for reuse. This operation locks the table exclusively, blocking all concurrent reads and writes until completion. It is resource-intensive, requiring double the table size in temporary storage during execution. Consequently, it should only be employed when space reclamation is critical, such as after bulk deletions or massive updates. Unlike standard vacuum, which leaves freed space available for future inserts, vacuum full shrinks the file on disk, offering immediate storage savings.

**Also worth reading:** [How to tune autovacuum configuration for better postgres performance?](https://l0t.me/knowledge/how_to_tune_autovacuum_configuration_for_better_postgres_performance.php) · [How can merchants turn payment fee optimization into a growth lever instead of a cost center?](https://l0t.me/knowledge/how_can_merchants_turn_payment_fee_optimization_into_a_growth_lever_instead_of_a_cost_center.php) · [How to optimize postgresql vacuum performance?](https://l0t.me/knowledge/how_to_optimize_postgresql_vacuum_performance.php)

Truncate, conversely, drops all rows instantly without scanning or locking individual tuples, making it vastly faster for clearing entire tables. However, truncate does not reclaim space within the table structure itself if you retain the table definition; it simply empties the data container. Use vacuum full when you need to shrink an existing table’s physical size after heavy data churn, particularly in environments where disk space is constrained and autovacuum cannot keep pace with write loads. Avoid it during peak traffic, as the exclusive lock will cause application timeouts. Truncate is preferable when you are resetting a table completely,不在乎 preserving existing row IDs or constraints, and when speed outweighs the need for gradual space reclamation. Always monitor autovacuum settings to prevent future bloat, ensuring your database maintains optimal performance without resorting to heavy maintenance operations.

## truncate behavior explained

Truncate is a DDL command that removes all rows from a table in a single, fast operation. It resets the table's storage and identity columns, and it cannot be rolled back in standard PostgreSQL. Because it operates at the storage level, it does not generate WAL for individual row deletions, making it significantly faster than a delete operation. However, it requires an exclusive lock on the table, blocking all concurrent reads and writes until the command completes.

Vacuum Full is a maintenance command used to reclaim disk space after massive deletions or updates that leave behind dead tuples. Unlike a standard vacuum, which only marks space as reusable, Vacuum Full actually reorganizes the table and rebuilds its indexes. This process is I/O intensive and also requires an exclusive lock, but it returns the table to its minimum size. Use Vacuum Full when disk space is critically low and standard autovacuum cannot keep up, or when you need to shrink a table after a one-time data purge.

## comparison of performance impacts

The distinction that settles the debate is whether the rows survive. TRUNCATE is not a compaction tool; it drops every row and returns the space to the OS in one shot, briefly locking the table. VACUUM FULL locks the table too, but rewrites the whole table into a fresh file, preserving data while shrinking the footprint. It needs roughly one extra table's worth of temporary disk and rebuilds every index, so it is slow and IO-heavy. Reach for it only when bloat is severe, rows must remain, and an online alternative like pg_repack cannot fit the maintenance window.

If the table is disposable — a staging import, a nightly reload, a scratch partition — TRUNCATE wins outright, since VACUUM FULL would spend minutes rewriting rows you intend to throw away anyway. On managed services like Amazon RDS and Aurora, both operations bite: the exclusive lock blocks traffic, and VACUUM FULL's disk spike can force storage scaling. Routine churn belongs to autovacuum; reserve VACUUM FULL for the rare table that has grown far beyond its live data and cannot be emptied.

## data retention differences

Vacuum full rewrites the entire table to eliminate dead tuples, preserving the existing schema, constraints, indexes, and any ongoing transactions. It can be run while the table remains accessible for reads and writes, though it acquires a exclusive lock for the duration of the rewrite. This makes vacuum full the safer choice when you need to reclaim storage without losing data, when foreign‑key relationships must stay intact, or when you cannot afford a full downtime because the operation can be scheduled during low‑traffic periods. The command also leaves sequence values untouched, so future inserts continue from the last used value.

Truncate, on the other hand, instantly removes all rows, releases the space back to the filesystem, and resets any serial or identity columns to their default start values. It drops constraints only in some configurations and cannot be rolled back in most production environments. Use truncate when you deliberately want to discard an entire dataset—such as for test resets, data migration cleanup, or when historical retention is no longer required—and you are comfortable with the permanent loss of that data.

## selecting the right method

Choosing between these operations comes down to whether the existing data must be preserved. TRUNCATE is the right choice when the goal is to remove every row from a table and start fresh, as it deallocates storage almost instantly without scanning individual tuples. However, it is an all-or-nothing operation that cannot be filtered and may be restricted by foreign key references from other tables.

VACUUM FULL should be used when you need to reclaim disk space consumed by dead tuples after large updates or deletes but cannot afford to lose the remaining rows. It rewrites the entire table into a new, compact file, returning unused space to the operating system—something a regular vacuum in managed environments like Amazon RDS or Aurora does not do. Because it takes an exclusive lock and requires additional disk space during the rewrite, it is best reserved for maintenance windows when data retention is non-negotiable and bloat is severely impacting storage or performance.

## vacuum full versus truncate comparison

| Factor | Use VACUUM FULL | Use TRUNCATE |
| --- | --- | --- |
| Data Retention | Keeps all existing rows while compacting the table. | Removes all rows from the table entirely. |
| Speed & Overhead | Slow; rewrites the entire table and its indexes. | Very fast; deallocates data pages with minimal overhead. |
| Locking | Holds an ACCESS EXCLUSIVE lock for a long duration. | Holds an ACCESS EXCLUSIVE lock, but only briefly. |
| Ideal Use Case | Use when a bloated table must retain its data. | Use when you need to empty a table completely. |

Use VACUUM FULL only as a last resort when a table is heavily bloated but still required, and you can afford extended downtime for a full rewrite. If all of its data is disposable, TRUNCATE is almost always faster, lighter on resources, and the far more practical choice in PostgreSQL.

## Quick answers

### Does vacuum full rebuild indexes?

Yes, vacuum full rebuilds the entire table and all associated indexes to remove dead tuples.

### Can truncate be reversed?

No, truncate is an irreversible operation that permanently deletes all data in the table.

### Which is faster for large tables?

Truncate is significantly faster because it does not scan the table or update indexes.

### Does vacuum full lock the table?

Yes, vacuum full acquires an exclusive lock, preventing other transactions from accessing the table.

Canonical: https://l0t.me/knowledge/when_should_i_use_postgres_vacuum_full_instead_of_truncate.php
Markdown: https://l0t.me/knowledge/when_should_i_use_postgres_vacuum_full_instead_of_truncate.php/index.md
