All rules Rule SR014 · LK
SurrealDB · beta
warning
LK · Locks & blocking
free in the CLI, --engine=surrealdb

Is an UPDATE of a whole table safe in a SurrealDB migration?

UPDATE of every record in a table

Warning: the statement succeeds, then writes fail, access changes, or the table is held up.

What happens

Observed on SurrealDB 3.0.2: an UPDATE over a table where one record fails its field TYPE rolls back every record the statement had already changed.

Why it is dangerous on a populated table

SurrealDB checks a schema change against new writes, not the records already stored, so an empty table hides it: on a populated one every old record is a write waiting to fail, and whole-table work runs for the length of the table in one transaction.

Fires on

UPDATE user SET plan = 'free';

The safe pattern

Add the predicate that limits the change, and run a backfill of a large table in batches from a job.

UPDATE user SET plan = 'free' WHERE plan IS NONE;

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 (2)

unset all
UPDATE user UNSET legacy_flag;
update all
UPDATE user SET plan = 'free';

Stays silent (4)

new table
DEFINE TABLE plan_defaults SCHEMALESS;
UPDATE plan_defaults SET tier = 'free';
record id
UPDATE user:admin SET plan = 'enterprise';
record range
UPDATE user:1..100 SET plan = 'free';
where
UPDATE user SET plan = 'free' WHERE plan IS NONE;

How to check locally

Catch this before it ships

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

npx bolvrk check migration.surql --engine=surrealdb