TailorDB Commands
Commands for managing TailorDB tables, data, and schema migrations.
tailordb
Manage TailorDB tables and data.
Usage
tailor-sdk tailordb [command]
Commands
| Command | Description |
|---|---|
tailordb erd | Generate ERD artifacts for TailorDB namespaces using Liam ERD. (beta) |
tailordb migration | Manage TailorDB schema migrations. |
tailordb truncate | Truncate (delete all records from) TailorDB tables. |
tailordb truncate
Truncate (delete all records from) TailorDB tables.
Usage
tailor-sdk tailordb truncate [options] [types]
Arguments
| Argument | Description | Required |
|---|---|---|
types | Type names to truncate | No |
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--yes | -y | Skip confirmation prompts | No | false |
--all | -a | Truncate all tables in all namespaces | No | false |
--namespace <NAMESPACE> | -n | Truncate all tables in specified namespace | No | - |
tailordb migration
Manage TailorDB schema migrations.
Usage
tailor-sdk tailordb migration [command]
Commands
| Command | Description |
|---|---|
tailordb migration generate | Generate migration files by detecting schema differences between current local types and the previous migration snapshot. |
tailordb migration set | Set migration checkpoint to a specific number. |
tailordb migration status | Show the current migration status for TailorDB namespaces, including applied and pending migrations. |
tailordb migration generate
Generate migration files by detecting schema differences between current local types and the previous migration snapshot.
Usage
tailor-sdk tailordb migration generate [options]
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--yes | -y | Skip confirmation prompts | No | false |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--name <NAME> | -n | Optional description for the migration | No | - |
--init | - | Delete existing migrations and start fresh | No | false |
tailordb migration set
Set migration checkpoint to a specific number.
Usage
tailor-sdk tailordb migration set [options] <number>
Arguments
| Argument | Description | Required |
|---|---|---|
number | Migration number to set (e.g., 0001 or 1) | Yes |
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--yes | -y | Skip confirmation prompts | No | false |
--namespace <NAMESPACE> | -n | Target TailorDB namespace (required if multiple namespaces exist) | No | - |
tailordb migration status
Show the current migration status for TailorDB namespaces, including applied and pending migrations.
Usage
tailor-sdk tailordb migration status [options]
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--namespace <NAMESPACE> | -n | Target TailorDB namespace (shows all namespaces if not specified) | No | - |
tailordb erd
Generate ERD artifacts for TailorDB namespaces using Liam ERD. (beta)
Usage
tailor-sdk tailordb erd [command]
Commands
| Command | Description |
|---|---|
tailordb erd export | Export Liam ERD dist from applied TailorDB schema. |
tailordb erd serve | Generate and serve ERD locally (liam build + serve dist). (beta) |
tailordb erd deploy | Deploy ERD static website for TailorDB namespace(s). |
tailordb erd export
Export Liam ERD dist from applied TailorDB schema.
Usage
tailor-sdk tailordb erd export [options]
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--json | -j | Output as JSON | No | false |
--namespace <NAMESPACE> | -n | TailorDB namespace name (optional if only one namespace is defined in config) | No | - |
--output <OUTPUT> | -o | Output directory path for tbls-compatible ERD JSON (writes to <outputDir>/<namespace>/schema.json) | No | ".tailor-sdk/erd" |
tailordb erd serve
Generate and serve ERD locally (liam build + serve dist). (beta)
Usage
tailor-sdk tailordb erd serve [options]
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--namespace <NAMESPACE> | -n | TailorDB namespace name (uses first namespace in config if not specified) | No | - |
tailordb erd deploy
Deploy ERD static website for TailorDB namespace(s).
Usage
tailor-sdk tailordb erd deploy [options]
Options
| Option | Alias | Description | Required | Default |
|---|---|---|---|---|
--workspace-id <WORKSPACE_ID> | -w | Workspace ID | No | - |
--profile <PROFILE> | -p | Workspace profile | No | - |
--config <CONFIG> | -c | Path to SDK config file | No | "tailor.config.ts" |
--json | -j | Output as JSON | No | false |
--namespace <NAMESPACE> | -n | TailorDB namespace name (optional - deploys all namespaces with erdSite if omitted) | No | - |
Usage Examples:
<span><span style="color: var(--shiki-token-comment)"># Truncate all tables in all namespaces (requires confirmation)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">truncate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--all</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Truncate all tables in all namespaces (skip confirmation)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">truncate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--all</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--yes</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Truncate all tables in a specific namespace</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">truncate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--namespace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">myNamespace</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Truncate specific types (namespace is auto-detected)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">truncate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">User</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">Post</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">Comment</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Truncate specific types with confirmation skipped</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">truncate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">User</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">Post</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--yes</span></span>
<span></span>
Notes:
- You must specify exactly one of:
--all,--namespace, or type names - When truncating specific types, the namespace is automatically detected from your config
- Confirmation prompts vary based on the operation:
--all: requires typingtruncate all--namespace: requires typingtruncate <namespace-name>- Specific types: requires typing
yes
- Use
--yesflag to skip confirmation prompts (useful for scripts and CI/CD)
Overview
The migration system detects field-level schema differences between your local type definitions and the previous snapshot, then generates migration files to safely apply those changes with data transformations.
Key Features:
- Local snapshot-based diff detection between current types and previous migration snapshot
- Transaction-wrapped data migrations for atomicity - all changes commit or rollback together
- Automatic execution during apply - pending migrations run as part of
tailor-sdk apply - TypeScript migration scripts - type-safe data transformations using Kysely
Usage Examples:
<span><span style="color: var(--shiki-token-comment)"># Generate migration for all schema changes</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Generate with a description</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--name</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"add email field to user"</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Generate without confirmation prompts</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--yes</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Delete existing migrations and start fresh (with confirmation)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--init</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Delete existing migrations and start fresh (skip confirmation)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--init</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--yes</span></span>
<span></span>
Generated Files:
Each migration creates a directory in the migrations folder with a 4-digit sequential number:
| File | Description |
|---|---|
0000/schema.json | Initial schema snapshot (first migration only) |
XXXX/diff.json | Schema diff from previous snapshot |
XXXX/migrate.ts | Data migration script (only when breaking changes) |
XXXX/db.ts | Generated Kysely types for the migration script |
Migration Script Structure:
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">type</span><span style="color: var(--shiki-color-text)"> { Transaction } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"./db"</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">function</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">main</span><span style="color: var(--shiki-color-text)">(trx</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Transaction</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Promise</span><span style="color: var(--shiki-color-text)"><</span><span style="color: var(--shiki-token-constant)">void</span><span style="color: var(--shiki-color-text)">> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// Your data migration logic here</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// All operations use the transaction object (trx)</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">trx</span><span style="color: var(--shiki-token-function)">.updateTable</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"User"</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-function)">.set</span><span style="color: var(--shiki-color-text)">({ newField</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"default value"</span><span style="color: var(--shiki-color-text)"> })</span><span style="color: var(--shiki-token-function)">.execute</span><span style="color: var(--shiki-color-text)">();</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
The db.ts file contains Kysely Transaction types that reflect the schema state before the migration runs. This ensures type-safe data transformations based on the actual database structure at that point in time.
The main function receives a Kysely transaction object. All database operations should use this trx object to ensure atomicity - if any operation fails, all changes are rolled back.
Editor Integration:
If the EDITOR environment variable is set, the generated script file will automatically open in your preferred editor:
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> EDITOR</span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-token-string)">vim</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span></span>
<span><span style="color: var(--shiki-token-comment)"># → After generation, vim opens XXXX/migrate.ts</span></span>
<span></span>
Usage Examples:
<span><span style="color: var(--shiki-token-comment)"># Set migration checkpoint to 0001 (with confirmation)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">set</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Set migration checkpoint without confirmation</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">set</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--yes</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Set for specific namespace</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">set</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">2</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--namespace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Reset to initial state (all migrations become pending)</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">set</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">0</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--yes</span></span>
<span></span>
Warning:
Setting the migration checkpoint changes which migrations will be executed on next apply:
- Forward (e.g., 0001 → 0003): Skips migrations 0002 and 0003
- Backward (e.g., 0003 → 0001): Migrations 0002 and 0003 become pending and will re-execute
The command always displays a warning and requires confirmation unless --yes is specified.
Usage Examples:
<span><span style="color: var(--shiki-token-comment)"># Show status for all namespaces</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">status</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Show status for specific namespace</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">status</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--namespace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span></span>
<span></span>
Example Output:
Namespace: tailordb
Current migration: 0001
Pending migrations:
- 0002: Add email field to user
- 0003: Remove deprecated status field
Configuration
Configure migrations in tailor.config.ts:
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">default</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">defineConfig</span><span style="color: var(--shiki-color-text)">({</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"my-app"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> db</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> tailordb</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> files</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">"./tailordb/*.ts"</span><span style="color: var(--shiki-color-text)">]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> migration</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> directory</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"./migrations"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// Optional: specify machine user for migration script execution</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// If not specified, the first machine user from auth.machineUsers is used</span></span>
<span><span style="color: var(--shiki-color-text)"> machineUser</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"admin-machine-user"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">});</span></span>
<span></span>
Configuration Options
| Option | Type | Description |
|---|---|---|
files | string[] | Glob patterns for TailorDB type definition files |
ignores | string[] | Glob patterns to ignore |
migration.directory | string | Directory path for migration files |
migration.machineUser | string | Machine user name for migration script execution (optional, defaults to first machine user from auth.machineUsers) |
Machine User Selection
When executing migration scripts, the system selects a machine user in the following priority:
- Explicit configuration:
migration.machineUserin db config - Auto-selection: First machine user from
auth.machineUsers
The machine user being used is logged during migration execution.
Migration Directory Structure
Migrations use a directory-based structure with 4-digit sequential numbering:
migrations/
├── 0000/ # Initial schema (number 0)
│ └── schema.json # Full schema snapshot
├── 0001/ # First change
│ ├── diff.json # Schema diff
│ ├── migrate.ts # Migration script (if breaking changes)
│ └── db.ts # Kysely types (if breaking changes)
├── 0002/ # Second change
│ └── diff.json
└── ...
0000- Initial schema snapshot (always starts at 0)0001- First schema change0002- Second schema change, etc.
Supported Schema Changes
| Change Type | Breaking? | Migration Script | Notes |
|---|---|---|---|
| Add optional field | No | No | Schema change only |
| Add required field | Yes | Yes | Script populates default values |
| Remove field | No | No | Schema change only - data is preserved |
| Change optional→required | Yes | Yes | Script sets defaults for null values |
| Change required→optional | No | No | Schema change only |
| Add index | No | No | Schema change only |
| Remove index | No | No | Schema change only |
| Add unique constraint | Yes | Yes | Script must resolve duplicate values |
| Remove unique constraint | No | No | Schema change only |
| Add enum value | No | No | Schema change only |
| Remove enum value | Yes | Yes | Script migrates records with removed values |
| Add type | No | No | Schema change only |
| Remove type | No | No | Schema change only - data is preserved |
| Change field type | - | - | Not supported - requires 3-step migration |
| Change array to single value | - | - | Not supported - requires 3-step migration |
| Change single value to array | - | - | Not supported - requires 3-step migration |
| Change foreign key relationship | Yes | Yes | Script updates existing references |
Unsupported Schema Changes
The following changes require a 3-step migration process:
Field Type Change
Field type changes (e.g., string → integer) are not directly supported. Use this migration strategy:
- Migration 1: Add a new field with the desired type (e.g.,
fieldName_new) and migrate data - Migration 2: Remove the old field
- Migration 3: Add the field with the original name and new type, migrate data from temporary field, then remove temporary field
Array Property Change
Changing between single value and array (e.g., array: false → array: true) is not directly supported. Use the same 3-step migration strategy as field type changes.
Example Workflow
-
Modify your type definition:
<span><span style="color: var(--shiki-token-comment)">// tailordb/user.ts</span></span> <span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">user</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.type</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"User"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span> <span><span style="color: var(--shiki-color-text)"> name</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.string</span><span style="color: var(--shiki-color-text)">()</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)"> email</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.string</span><span style="color: var(--shiki-color-text)">()</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// ← New required field</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">...</span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.</span><span style="color: var(--shiki-token-constant)">fields</span><span style="color: var(--shiki-token-function)">.timestamps</span><span style="color: var(--shiki-color-text)">()</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)">});</span></span> <span></span> -
Generate migration:
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">migration</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">generate</span></span> <span><span style="color: var(--shiki-token-comment)"># Output: Generated migration 0001</span></span> <span><span style="color: var(--shiki-token-comment)"># Diff file: ./migrations/0001/diff.json</span></span> <span><span style="color: var(--shiki-token-comment)"># Migration script: ./migrations/0001/migrate.ts</span></span> <span><span style="color: var(--shiki-token-comment)"># DB types: ./migrations/0001/db.ts</span></span> <span></span> -
Edit the migration script (
0001/migrate.ts):<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">type</span><span style="color: var(--shiki-color-text)"> { Transaction } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"./db"</span><span style="color: var(--shiki-color-text)">;</span></span> <span></span> <span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">function</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">main</span><span style="color: var(--shiki-color-text)">(trx</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Transaction</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Promise</span><span style="color: var(--shiki-color-text)"><</span><span style="color: var(--shiki-token-constant)">void</span><span style="color: var(--shiki-color-text)">> {</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> trx</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">.updateTable</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"User"</span><span style="color: var(--shiki-color-text)">)</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">.set</span><span style="color: var(--shiki-color-text)">({ email</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"default@example.com"</span><span style="color: var(--shiki-color-text)"> })</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">.where</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"email"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"is"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">null</span><span style="color: var(--shiki-color-text)">)</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">.execute</span><span style="color: var(--shiki-color-text)">();</span></span> <span><span style="color: var(--shiki-color-text)">}</span></span> <span></span> -
Apply migration:
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">apply</span></span> <span><span style="color: var(--shiki-token-comment)"># Migrations are automatically executed during apply</span></span> <span></span>
Automatic Migration Execution
When running tailor-sdk apply, pending migration scripts are automatically executed as part of the deployment process.
How It Works
- Pending Migration Detection: Identifies migration scripts that haven't been executed yet
- Two-Stage Type Update: For breaking changes (required fields, type changes):
- Pre-Migration: New fields are added as
optionalfirst - Script Execution: Migration scripts run to populate data
- Post-Migration: Fields are changed to
required, deletions are applied
- Pre-Migration: New fields are added as
Execution Flow
tailor-sdk apply
│
├── Detect Pending Migrations
│
├── [If pending migrations exist]
│ ├── Pre-Migration: Add fields as optional
│ ├── Execute Migration Scripts (TestExecScript API)
│ └── Post-Migration: Apply required, deletions
│
└── Continue with normal apply flow
Requirements for Automatic Migration
- Migrations configured:
migrationspath set in db config - Auth configured: Auth service with machine users
- Kysely generator:
@tailor-platform/kysely-typegenerator configured
Schema Verification
By default, tailor-sdk apply performs two schema verifications:
- Local schema check: Ensures local type definitions match the migration snapshot
- Remote schema check: Ensures remote schema matches the expected state based on migration history
If remote schema drift is detected, you'll see an error like:
✖ Remote schema drift detected:
Namespace: tailordb
Remote migration: 0007
Differences:
Type 'User':
- Field 'email': required: remote=false, expected=true
ℹ This may indicate:
- Another developer applied different migrations
- Manual schema changes were made directly
- Migration history is out of sync
ℹ Use '--no-schema-check' to skip this check (not recommended).
Skipping Schema Check
To skip both local and remote schema verification (not recommended for production):
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">apply</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--no-schema-check</span></span>
<span></span>
Warning: Skipping schema checks may result in applying migrations to an inconsistent state.
Example Output
ℹ Found 2 pending migration(s) to execute.
ℹ Executing 2 pending migration(s)...
ℹ Using machine user: admin-machine-user
✔ Migration tailordb/0002 completed successfully
✔ Migration tailordb/0003 completed successfully
✔ All migrations completed successfully.
✔ Successfully applied changes.
Troubleshooting
Remote schema drift detected
Cause: The remote schema doesn't match the expected state based on migration history. This can happen when:
- Another developer applied different migrations
- Schema was changed manually outside of migrations
- Migration history is out of sync
Solution:
- Check migration status: Run
tailor-sdk tailordb migration statusto see current state - Sync with team: Ensure all team members have the same migration files
- Reset if needed: Use
tailor-sdk tailordb migration set <number>to reset migration checkpoint - Force apply (use with caution): Use
--no-schema-checkto skip verification
"Machine user not found"
Cause: Specified machine user doesn't exist in auth configuration.
Solution:
- Check available users: The error message lists available machine users
- Add machine user to your auth config:
<span><span style="color: var(--shiki-color-text)">machineUsers</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"your-user-name"</span><span style="color: var(--shiki-color-text)">: {</span></span> <span><span style="color: var(--shiki-color-text)"> attributes</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> { role</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"ADMIN"</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)">}</span></span> <span></span> - Run
tailor-sdk applyto deploy the auth config - Retry migration
Migration script execution fails
Cause: Runtime error in your data migration logic.
Solution:
- Check the error message for the failing query/operation
- Test your script logic locally if possible
- Fix the script
- Apply again:
tailor-sdk apply
Notes:
- This command is a beta feature and may introduce breaking changes in future releases
Usage Examples:
<span><span style="color: var(--shiki-token-comment)"># Deploy ERD for all namespaces with erdSite configured</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">erd</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">deploy</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Deploy ERD for a specific namespace</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">erd</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">deploy</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--namespace</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">myNamespace</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Deploy ERD with JSON output</span></span>
<span><span style="color: var(--shiki-token-function)">tailor-sdk</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tailordb</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">erd</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">deploy</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">--json</span></span>
<span></span>
Notes:
- Requires
erdSiteto be configured intailor.config.tsfor each namespace you want to deploy - Example config:
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">default</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">defineConfig</span><span style="color: var(--shiki-color-text)">({</span></span> <span><span style="color: var(--shiki-color-text)"> db</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span> <span><span style="color: var(--shiki-color-text)"> myNamespace</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span> <span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// ... table definitions</span></span> <span><span style="color: var(--shiki-color-text)"> erdSite</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"my-erd-site-name"</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span> <span><span style="color: var(--shiki-color-text)">});</span></span> <span></span>