All rules Rule SL007 · DW
SQLite · beta
warning
DW · Deploy window
free in the CLI, --engine=sqlite

Is it safe to rename a column or table in SQLite during a deploy?

RENAME COLUMN or RENAME TABLE during a deploy

Warning: it works, but holds the single write lock or breaks the previous release.

What happens

A rename is instant in SQLite, and that is the problem: the moment it commits, every process still running the previous release fails on the old name. Views and triggers are rewritten to the new name, but application SQL is not.

Why it is dangerous on a populated table

SQLite holds one write lock for the whole database, so anything that rebuilds a table blocks every writer for as long as the copy takes, and that time grows with the table.

Fires on

ALTER TABLE orders RENAME COLUMN qty TO quantity;

The safe pattern

Expand and contract: add the new column, dual-write from the application, backfill, switch readers, then drop the old column in a later release. For a table, create the new one, copy, and swap only when no deployed code reads the old name.

ALTER TABLE orders ADD COLUMN quantity INTEGER;
-- dual-write from the application; backfill in batches
-- later release, after readers moved:
--    ALTER TABLE orders DROP COLUMN qty;

Fixtures

The rule ships with these files and the test suite runs them on every change: the first set must fire, the second must stay silent.

Fires (3)

rename column
ALTER TABLE orders RENAME COLUMN qty TO quantity;
rename live table onto dropped name
DROP TABLE orders;
ALTER TABLE orders_staging RENAME TO orders;
rename table
ALTER TABLE orders RENAME TO purchases;

Stays silent (2)

rename finishing rebuild
PRAGMA foreign_keys = OFF;
BEGIN;
CREATE TABLE orders_new (id INTEGER PRIMARY KEY, qty INTEGER NOT NULL);
INSERT INTO orders_new SELECT id, qty FROM orders;
DROP TABLE orders;
ALTER TABLE orders_new RENAME TO orders;
PRAGMA foreign_key_check;
COMMIT;
PRAGMA foreign_keys = ON;
rename new table
CREATE TABLE tmp_orders (id INTEGER PRIMARY KEY);
ALTER TABLE tmp_orders RENAME COLUMN id TO order_id;

How to check locally

Catch this before it ships

SQLite support is in beta: this rule runs locally in the free CLI, static only, and not in the hosted service yet. No install, nothing leaves your machine:

npx bolvrk check migration.sql --engine=sqlite