warn-timescale-columnstore-ddl
TimescaleDB rejects this ALTER on a hypertable that has compression / columnstore enabled.
- operation
- Tables
- lock taken
- no table lock
- remediation
- Multi-step plan
- category
- Extensions
- Breaks a rolling deploy
What triggers it
ctx.tableExtensions.isHypertable true, compressionEnabled strictly true, and an AlterTableStmt containing a subcommand in the blocked set: AT_AlterColumnType, AT_SetStorage, AT_EnableRowSecurity, AT_DisableRowSecurity, AT_ForceRowSecurity, AT_NoForceRowSecurity. The first match in cmds wins, and its name supplies the column named in the message.
What does not
Every run without --database-url — the identical ALTER against an uncompressed hypertable is perfectly legal, so guessing would be wrong (requiresDatabaseUrl is set). A hypertable whose compressionEnabled is false or undefined, which the strict !== true test treats the same way. Hypertable ALTER forms outside the six blocked subtypes, which fall through to MP105. Ordinary tables.
Where it applies
Applies to every PostgreSQL version MigrationPilot targets. It only fires on tables managed by TimescaleDB. It needs --database-url: without a connection it has nothing to read and stays silent.
The lock, and what it blocks
No lock, because the statement never gets far enough to hold one usefully — TimescaleDB rejects it with operation not supported on hypertables that have columnstore enabled. The migration stops at that statement with everything before it already applied, which is why this is critical rather than a warning: the outcome is known, not merely likely.
Why it matters
This is not a slow path — the statement fails. TimescaleDB answers "operation not supported on hypertables that have columnstore enabled", and the migration stops partway through with whatever ran before it already applied. Getting the change through is a procedure rather than a fix: stop the columnstore policy, convert the compressed chunks back to rowstore, disable the columnstore, apply the change, then re-enable and restore the policy. Two of those steps rewrite every chunk, so they belong in their own maintenance window.
Unsafe, and safe
Flagged
-- metrics is a hypertable with the columnstore enabled ALTER TABLE metrics ALTER COLUMN value TYPE numeric; -- ERROR: operation not supported on hypertables that have columnstore enabled
Safe alternative
-- Confirm the columnstore state first — it decides whether this is a -- one-line ALTER or a whole-hypertable maintenance window. SELECT hypertable_name, compression_enabled, num_chunks FROM timescaledb_information.hypertables WHERE hypertable_name = 'metrics';
Deploy and transaction boundaries
Getting the change through is a five-step procedure — remove the columnstore policy, convert compressed chunks back to rowstore, disable the columnstore, apply the ALTER, then re-enable and restore the policy. Two of those steps move every row in the hypertable, so it belongs in its own maintenance window rather than inside a migration run.
What it assumes
The blocked list is a fixed set of six subtypes taken from TimescaleDB's documented restrictions rather than from the installed extension's version, so a release that lifts one of them, or adds another, is not tracked. compression_enabled is a hypertable-level policy flag, so a hypertable with the columnstore enabled but no chunks actually converted yet is still reported. And the flag is read from the database you connected to, which may not be the one the migration will run against.
This rule reads live catalogue state, so it says nothing at all without --database-url. That is the trade: no connection, no guess.
What the CLI prints
✗ [MP111] CRITICAL (line 2) ALTER COLUMN ... TYPE on "value" against "metrics", a hypertable with the columnstore enabled. TimescaleDB rejects this with "operation not supported on hypertables that have columnstore enabled". The migration will fail here, not run slowly. Safe alternative: -- Confirm the columnstore state first: SELECT hypertable_name, compression_enabled, num_chunks FROM timescaledb_information.hypertables WHERE hypertable_name = 'metrics'; -- Getting this change through means unwinding the columnstore and putting it back: -- 1. remove the columnstore policy for metrics -- 2. convert the compressed chunks back to rowstore -- 3. disable the columnstore on the hypertable -- 4. run: ALTER TABLE metrics ALTER COLUMN value TYPE numeric -- 5. re-enable the columnstore and restore the policy -- -- Steps 2 and 5 move all of the hypertable's data, so schedule this as its own -- maintenance operation rather than a step inside a migration run. Why: TimescaleDB blocks several ALTER forms on a hypertable whose chunks are in the columnstore, and answers with "operation not supported on hypertables that have columnstore enabled". This is not a slow path: the statement fails. Getting it through means stopping the columnstore policy, converting the chunks back to rowstore, disabling the columnstore, applying the change, then putting all of it back: a long, data-moving procedure that does not belong in the middle of an ordinary migration run. Docs: https://migrationpilot.dev/rules/mp111
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. The catalogue figures come from the production context this rule documents.
Turning it off
For one statement, put a comment on the line before it:
-- migrationpilot-disable MP111 ALTER TABLE metrics ALTER COLUMN value TYPE numeric;
For the whole project, in .migrationpilotrc.yml — by name or by id:
rules:
MP111: false
# or keep it, and downgrade it
rules:
MP111:
severity: warningTry 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 MP111 in the playground