docs/sql-reference/statements/vacuum.mdx
The VACUUM statement rebuilds the database file to reclaim unused space, defragment tables and indexes, and reduce the file size. Two forms are supported: VACUUM rebuilds the current database in place, while VACUUM INTO writes a compacted copy to a new file without modifying the source.
VACUUM [schema-name];
VACUUM [schema-name] INTO filename;
| Parameter | Description |
|---|---|
schema-name | The database to vacuum. For in-place VACUUM only main is supported. For VACUUM INTO any attached schema is accepted; temp is a no-op and produces no file. Defaults to main. |
filename | A string literal giving the destination file path for VACUUM INTO. Bind parameters are not accepted. |
These rules apply to both VACUUM and VACUUM INTO:
BEGIN transaction.query_only mode.auto_vacuum = incremental. Incremental autovacuum is not supported.In-place VACUUM rebuilds the main database by writing a compacted image into an internal temp database and then copying those pages back over the original file. When it completes, unused pages have been released and all storage-backed objects have been recreated.
sqlite_sequence counters used by AUTOINCREMENT columns are preserved.In addition to the common requirements:
main database is supported. Vacuuming an attached schema in place is not supported yet.When the database uses MVCC (PRAGMA journal_mode = mvcc), additional rules apply to in-place VACUUM:
VACUUM returns an error — run PRAGMA wal_checkpoint(TRUNCATE) first.VACUUM returns a busy error if one is found.VACUUM INTO builds a compacted copy of the database at the given path and leaves the source database untouched. The destination is a fully self-contained database file that can be opened independently.
filename containing all user tables, indexes, triggers, views, and virtual table content from the source.sqlite_sequence counters used by AUTOINCREMENT columns are preserved.In addition to the common requirements:
VACUUM temp INTO filename is a no-op and does not create a file, matching SQLite's behavior.VACUUM INTO takes a consistent view of the source by starting an implicit read transaction for the duration of the copy, so the destination always reflects a single snapshot of the source even if other connections write to it during the copy.
-- Reclaim space and defragment the current database
VACUUM;
VACUUM INTO 'backup.db';
The source database is unchanged. backup.db can be opened as a standalone database:
tursodb backup.db
ATTACH DATABASE 'archive.db' AS archive;
-- Write a compacted copy of the archive schema to a new file
VACUUM archive INTO 'archive-compact.db';
Because VACUUM INTO copies from a consistent snapshot, it is a simple way to capture a point-in-time backup of an active database:
VACUUM INTO '/var/backups/app-2026-04-23.db';
After bulk deletes or long-running workloads that leave indexes fragmented, VACUUM rebuilds the indexes and often improves scan speed:
DELETE FROM events WHERE created_at < '2025-01-01';
VACUUM;
| Error | Cause |
|---|---|
VACUUM is an experimental feature. Enable with --experimental-vacuum flag | In-place VACUUM used in a release build without the experimental flag. |
VACUUM is only supported for the main database; schema '<name>' is not supported yet | In-place VACUUM schema-name with a schema other than main. |
Cannot execute VACUUM in query_only mode | VACUUM or VACUUM INTO run on a connection where PRAGMA query_only is set. |
cannot VACUUM from within a transaction / cannot VACUUM INTO from within a transaction | Run inside an explicit BEGIN. |
cannot VACUUM - SQL statements in progress | Another statement is still active on the same connection. |
Incremental auto-vacuum is not supported | The source database has auto_vacuum = incremental. Applies to both VACUUM and VACUUM INTO. |
VACUUM requires a WAL-mode database | In-place VACUUM on a non-WAL database. |
cannot VACUUM an in-memory database | In-place VACUUM on an in-memory database. |
ReadOnly | In-place VACUUM on a read-only database. |
cannot VACUUM while experimental multiprocess WAL is active in another process | In-place VACUUM while another process holds the multi-process WAL. |
cannot VACUUM an MVCC database with uncheckpointed changes; run PRAGMA wal_checkpoint(TRUNCATE) first | In-place VACUUM on an MVCC database with pending log entries. |
output file already exists: <path> | The destination for VACUUM INTO already exists. |
VACUUM INTO path cannot be empty | VACUUM INTO '' was used. |
VACUUM INTO requires a string literal path | A non-literal expression (for example a bind parameter) was used for the destination. |
no such database: <name> | VACUUM <schema> INTO referenced an unknown schema. |
VACUUMauto_vacuum, journal_mode, query_only, and wal_checkpointVACUUM INTO