Database migrations
Create plugin-owned tables with versioned SQL migrations.
Migration files
Place SQL files in the root migrations/ directory of your package:
hello-plugin/
package.json
index.js
migrations/
0001_create_events.sql
0002_add_processed_at.sql
Files are applied in alphabetical order. Use zero-padded numeric prefixes and ensure the directory is included in the package's published files.
Plugin schema
The installer derives a schema from the package's final name segment. For example, @sellforge-plugin/hello maps to plugin_hello. Different scopes with the same final package name produce the same schema name, so choose a unique slug within the deployment.
Each migration runs in its own transaction with a local search path set to the plugin schema followed by public.
CREATE TABLE IF NOT EXISTS processed_orders (
order_id text PRIMARY KEY,
processed_at timestamptz NOT NULL DEFAULT now()
);
The table above is created in the plugin schema. This local migration search path does not automatically apply to later ctx.db queries.
Migration history
The runner records each file's name and SHA-256 checksum in plugin_migrations. It skips previously applied files with the same checksum and rejects a changed file that has already run.
Create a new migration when changing an installed schema. Preserve earlier migration files unchanged.
SQL restrictions
The validator rejects statements including DROP SCHEMA, changing search_path, grants/revokes, and user, role, or database creation/alteration. It also rejects recognized writes against public or core tables.
Keep migration changes within the plugin's own schema. The validator is a set of checks, not a general-purpose SQL sandbox.
Uninstall behavior
Uninstalling normally removes the installed record while preserving plugin data. The explicit drop_data=true option drops the plugin schema and its migration history. See Installation.
Found something unclear? Let us know