MP066warning

warn-autovacuum-disabled

Disabling autovacuum causes table bloat and risks transaction ID wraparound.

operation
Tables
lock taken
no table lock
remediation
Manual rewrite
category
Types & schema style

What triggers it

A CreateStmt with a WITH (autovacuum_enabled = false) storage option, or the AT_SetRelOptions subtype of ALTER TABLE ... SET (autovacuum_enabled = false) — both checked by scanning the option list's DefElem entries for defname === 'autovacuum_enabled' with a string value of 'false'.

What does not

CREATE TABLE or ALTER TABLE ... SET with any other storage option, or with autovacuum_enabled set to true or anything other than the literal string 'false', and any AlterTableCmd subtype other than AT_SetRelOptions.

Where it applies

Applies to every PostgreSQL version MigrationPilot targets. It works on the SQL text alone — no database connection needed.

The lock, and what it blocks

No lock is named in the source — the concern isn't blocking, it's what happens after: without autovacuum, dead tuples build up and the table's transaction id counter stops advancing, pushing it toward a wraparound shutdown over time.

Why it matters

Autovacuum prevents table bloat by reclaiming dead tuples, and prevents transaction ID wraparound — which can freeze the entire database. Disabling autovacuum is occasionally justified for temporary bulk-load staging tables, but is dangerous for any table that serves production traffic.

The operation, and the mitigation

Flagged

CREATE TABLE staging_data (id INT)
  WITH (autovacuum_enabled = false);

Mitigated — still flagged

-- Create with autovacuum disabled for bulk load, then re-enable
CREATE TABLE staging_data (id INT)
  WITH (autovacuum_enabled = false);
-- After bulk load:
ALTER TABLE staging_data SET (autovacuum_enabled = true);

This operation is irreversible, so there is no syntax that makes it safe. The second block is what care looks like — and MigrationPilot still flags it. The mitigation is process: confirm nothing reads the object, keep a way back, and do it in a window where you can watch.

What it assumes

The rule fires the same way whether this is a permanent production table or a short-lived staging table for a bulk load, where disabling autovacuum temporarily is a common, legitimate optimization — it only sees that the option was set, not the table's purpose.

What the CLI prints

migrationpilot analyze migration.sql
⚠ [MP066] WARNING (line 1)
  Table "staging_data" has autovacuum disabled. This causes table bloat and risks transaction ID wraparound. Re-enable autovacuum after bulk loading.

  Why: Autovacuum prevents table bloat by reclaiming dead tuples, and prevents transaction ID wraparound, which can freeze the entire database. Disabling autovacuum is occasionally justified for temporary bulk-load staging tables, but is dangerous for any table that serves production traffic.
  Docs: https://migrationpilot.dev/rules/mp066

Generated by running the CLI's own formatter over the flagged example above, so it is the text the tool actually produces. A real run also reports the other rules that fire on the same statement; those blocks are left out here.

Turning it off

For one statement, put a comment on the line before it:

-- migrationpilot-disable MP066
CREATE TABLE staging_data (id INT)

For the whole project, in .migrationpilotrc.yml — by name or by id:

.migrationpilotrc.yml
rules:
  MP066: false

# or keep it, and downgrade it
rules:
  MP066:
    severity: warning

Try it

Open this rule's flagged example in the playground. It runs in your browser — edit it and watch the finding appear and disappear.

Run MP066 in the playground