Skip to content
DocsPlugin development

Database migrations

Create plugin-owned tables with versioned SQL migrations.

Migration files

Place SQL files in the root migrations/ directory of your package:

text
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.

sql
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.

Source reviewed Checked against kernel fe5c475.

Found something unclear? Let us know

Start exploring

NavigateOpenEscClose