SyndrDB's migration system provides version control for database schemas. Migrations track schema changes over time, enable rollbacks, and ensure consistency across environments.
The migration system provides:
| State | Description |
|---|---|
| PENDING | Migration created but not yet applied |
| APPLIED | Migration successfully executed |
| FAILED | Migration execution failed |
| ROLLED_BACK | Migration was applied then rolled back |
| Setting | Default | Description |
|---|---|---|
MaxMigrationCommands |
1000 | Maximum commands per migration |
MigrationPerformanceThreshold |
1.0s | Performance warning threshold |
MigrationTimeoutSeconds |
300 | Execution timeout (5 minutes) |
RequireExplicitDownCommands |
false | Require manual DOWN commands |
Creates a new migration with schema change commands. The migration is validated but not applied until explicitly executed with APPLY MIGRATION.
START MIGRATION [WITH DESCRIPTION "description"]
command1;
command2;
...
COMMIT
| Component | Description | Required |
|---|---|---|
| WITH DESCRIPTION | Human-readable migration description | No |
| commands | SyndrDB commands to execute | Yes |
| COMMIT | Marks end of migration definition | Yes |
Optional description field:
Migrations can contain these commands:
CREATE BUNDLEUPDATE BUNDLE (rename, add/remove fields, add/remove relationships)DROP BUNDLECREATE INDEXDROP INDEXADD DOCUMENT (for seed data)-- Create a new bundle
START MIGRATION WITH DESCRIPTION "Add Users bundle"
CREATE BUNDLE "Users" WITH FIELDS (
{"id", STRING, true, true},
{"email", STRING, true, true},
{"created_at", DATETIME, true, false}
);
COMMIT
-- Add multiple bundles with relationships
START MIGRATION WITH DESCRIPTION "Add e-commerce schema"
CREATE BUNDLE "Products" WITH FIELDS (
{"id", STRING, true, true},
{"name", STRING, true, false},
{"price", FLOAT, true, false}
);
CREATE BUNDLE "Orders" WITH FIELDS (
{"id", STRING, true, true},
{"user_id", STRING, true, false},
{"total", FLOAT, true, false}
);
UPDATE BUNDLE "Orders"
ADD RELATIONSHIP "product_orders"
FROM BUNDLE "Orders" TO BUNDLE "Products";
COMMIT
-- Create bundle and add initial data
START MIGRATION WITH DESCRIPTION "Add Roles with defaults"
CREATE BUNDLE "Roles" WITH FIELDS (
{"id", STRING, true, true},
{"name", STRING, true, true},
{"permissions", JSON, true, false}
);
ADD DOCUMENT TO BUNDLE "Roles" WITH VALUES (
{"id": "admin", "name": "Administrator", "permissions": ["*"]}
);
ADD DOCUMENT TO BUNDLE "Roles" WITH VALUES (
{"id": "user", "name": "Regular User", "permissions": ["read"]}
);
COMMIT
-- Description is optional
START MIGRATION
UPDATE BUNDLE "Users"
ADD FIELD {"phone", STRING, false, false};
COMMIT
USE "database" first)VALIDATE MIGRATION)PENDING stateRequireExplicitDownCommands = true)| Error | Cause | Solution |
|---|---|---|
no active database |
No database selected | Use USE "database" first |
migration must contain at least one command |
Empty command body | Add at least one command |
description exceeds 500 character limit |
Description too long | Shorten description |
migration service not initialized |
System error | Check server configuration |
The migration system attempts to auto-generate rollback commands:
CREATE BUNDLE → DROP BUNDLEDROP BUNDLE → CREATE BUNDLE (if reversible)ADD FIELD → REMOVE FIELDUPDATE BUNDLE SET NAME → UPDATE BUNDLE SET NAME (reverse)If commands cannot be reversed automatically:
RequireExplicitDownCommands = true to enforce manual DOWN commandsDO:
VALIDATE MIGRATION)DON'T:
-- Select database
USE "production";
-- Create migration for user profile feature
START MIGRATION WITH DESCRIPTION "Add user profiles and preferences"
-- Add profile bundle
CREATE BUNDLE "UserProfiles" WITH FIELDS (
{"user_id", STRING, true, true},
{"bio", TEXT, false, false},
{"avatar_url", STRING, false, false},
{"created_at", DATETIME, true, false}
);
-- Add preferences bundle
CREATE BUNDLE "UserPreferences" WITH FIELDS (
{"user_id", STRING, true, true},
{"theme", STRING, true, false},
{"notifications", BOOLEAN, true, false}
);
-- Link to Users bundle
UPDATE BUNDLE "Users"
ADD RELATIONSHIP "user_profile"
FROM BUNDLE "Users" TO BUNDLE "UserProfiles";
UPDATE BUNDLE "Users"
ADD RELATIONSHIP "user_preferences"
FROM BUNDLE "Users" TO BUNDLE "UserPreferences";
COMMIT
-- Response: Migration created successfully
-- {
-- "status": "success",
-- "message": "Migration created successfully",
-- "migration": {
-- "Version": 1,
-- "Status": "PENDING",
-- "Description": "Add user profiles and preferences",
-- ...
-- }
-- }
Lists all migrations for the current database with their version numbers, status, and metadata.
SHOW MIGRATIONS FOR "database_name" [WHERE field == "value"]
| Component | Description | Required |
|---|---|---|
| database_name | Name of database to show migrations for | Yes |
| WHERE clause | Filter migrations by field | No |
Filter migrations using a WHERE clause:
SHOW MIGRATIONS FOR "MyApp" WHERE Status == "PENDING"
SHOW MIGRATIONS FOR "MyApp" WHERE Status == "APPLIED"
-- Show all migrations for database
USE "production";
SHOW MIGRATIONS FOR "production"
-- Show only pending migrations
SHOW MIGRATIONS FOR "production" WHERE Status == "PENDING"
-- Show only applied migrations
SHOW MIGRATIONS FOR "production" WHERE Status == "APPLIED"
-- Show failed migrations
SHOW MIGRATIONS FOR "production" WHERE Status == "FAILED"
{
"status": "success",
"database": "production",
"currentVersion": 5,
"migrations": [
{
"Version": 1,
"Status": "APPLIED",
"Description": "Initial schema",
"CreatedAt": "2024-01-10T10:00:00Z",
"AppliedAt": "2024-01-10T10:05:00Z",
"CommandCount": 3
},
{
"Version": 2,
"Status": "APPLIED",
"Description": "Add user profiles",
"CreatedAt": "2024-01-11T14:00:00Z",
"AppliedAt": "2024-01-11T14:02:00Z",
"CommandCount": 5
},
{
"Version": 3,
"Status": "PENDING",
"Description": "Add product categories",
"CreatedAt": "2024-01-12T09:00:00Z",
"CommandCount": 2
}
]
}
Each migration includes:
| Error | Cause | Solution |
|---|---|---|
no active database |
No database selected | Use USE "database" first |
migration service not initialized |
System error | Check server configuration |
DO:
currentVersion to understand database stateDON'T:
-- Switch to database
USE "production";
-- Show all migrations
SHOW MIGRATIONS FOR "production";
-- Output shows current version is 2, with 1 pending migration
-- {
-- "currentVersion": 2,
-- "migrations": [
-- {"Version": 1, "Status": "APPLIED", "Description": "Initial schema"},
-- {"Version": 2, "Status": "APPLIED", "Description": "Add user profiles"},
-- {"Version": 3, "Status": "PENDING", "Description": "Add categories"}
-- ]
-- }
-- Show only pending migrations to see what needs to be applied
SHOW MIGRATIONS FOR "production" WHERE Status == "PENDING";
-- Shows only version 3
-- Show only applied migrations for audit trail
SHOW MIGRATIONS FOR "production" WHERE Status == "APPLIED";
-- Shows versions 1 and 2
Executes a pending migration, applying all its commands to the database. This permanently modifies the database schema.
APPLY MIGRATION WITH VERSION <number> [FORCE]
| Component | Description | Required |
|---|---|---|
| VERSION number | Version number of migration to apply | Yes |
| FORCE | Skip validation warnings | No |
The FORCE flag controls warning behavior:
WARNING: Using FORCE can lead to data loss or schema corruption. Only use when you understand the warnings and accept the risks.
-- Apply next migration
APPLY MIGRATION WITH VERSION 3
-- Apply migration even if validation warnings exist
APPLY MIGRATION WITH VERSION 3 FORCE
Before execution, the migration undergoes 5 validation phases:
| Phase | Check | Blocking |
|---|---|---|
| 1. Syntax | Command syntax is valid | Yes |
| 2. Semantics | Commands reference existing objects | Yes |
| 3. Constraints | No constraint violations | Yes |
| 4. Performance | Estimated execution time | Warning |
| 5. Reversibility | Can be rolled back | Warning |
| Error | Cause | Solution |
|---|---|---|
no active database |
No database selected | Use USE "database" first |
migration not found |
Invalid version number | Use SHOW MIGRATIONS to see versions |
migration not in PENDING state |
Already applied or failed | Check migration status |
validation failed |
Syntax, semantic, or constraint errors | Review validation report, fix migration |
performance warning |
Estimated slow execution | Review commands, use FORCE if acceptable |
not reversible |
Cannot auto-generate DOWN commands | Manually create DOWN commands or use FORCE |
Migrations must be applied in order:
DO:
VALIDATE MIGRATION)VALIDATE ROLLBACK)DON'T:
-- Switch to database
USE "production";
-- Show pending migrations
SHOW MIGRATIONS FOR "production" WHERE Status == "PENDING";
-- Shows version 3 is pending
-- Validate before applying
VALIDATE MIGRATION WITH VERSION 3;
-- Review validation report...
-- {
-- "syntaxPhase": {"passed": true},
-- "semanticPhase": {"passed": true},
-- "constraintPhase": {"passed": true},
-- "performancePhase": {"passed": true, "warnings": []},
-- "reversibilityPhase": {"passed": true}
-- }
-- Validation passed, safe to apply
APPLY MIGRATION WITH VERSION 3;
-- Response: {
-- "status": "success",
-- "message": "Migration version 3 applied successfully",
-- "version": 3,
-- "force": false
-- }
-- Verify migration was applied
SHOW MIGRATIONS FOR "production";
-- Shows version 3 now has Status = "APPLIED"
-- Validate migration
VALIDATE MIGRATION WITH VERSION 4;
-- Report shows performance warning:
-- {
-- "performancePhase": {
-- "passed": false,
-- "warnings": ["Migration estimated to take 3.5s, exceeds threshold of 1.0s"]
-- }
-- }
-- Review warning - it's a large data import, expected to be slow
-- Decision: Acceptable for off-peak application
-- Apply with FORCE to override warning
APPLY MIGRATION WITH VERSION 4 FORCE;
-- Response: {
-- "status": "success",
-- "message": "Migration version 4 applied successfully",
-- "version": 4,
-- "force": true
-- }
Reverts the database to a previous migration version by executing DOWN commands in reverse order.
APPLY ROLLBACK TO VERSION <number>
| Component | Description | Required |
|---|---|---|
| VERSION number | Target version to rollback to | Yes |
-- Current version: 5, rollback to 4
APPLY ROLLBACK TO VERSION 4
-- Current version: 5, rollback to 2
APPLY ROLLBACK TO VERSION 2
-- Executes: V5 DOWN, V4 DOWN, V3 DOWN
Rollbacks execute in strict reverse order:
Current: V5 → Target: V2
Execution: V5 DOWN → V4 DOWN → V3 DOWN
Result: Database at V2
Cannot skip versions - must rollback through each version sequentially.
Rollback requires DOWN commands for each migration:
VALIDATE ROLLBACK to check if rollback is possible| Error | Cause | Solution |
|---|---|---|
no active database |
No database selected | Use USE "database" first |
invalid target version |
Target >= current version | Can only rollback to lower version |
missing DOWN commands |
Migration lacks DOWN commands | Manually create DOWN commands |
rollback failed |
DOWN command execution failed | Review error, restore from backup |
TODO: Approval token validation will be added
DO:
VALIDATE ROLLBACK)DON'T:
-- Switch to database
USE "production";
-- Check current version
SHOW MIGRATIONS FOR "production";
-- Current version: 5
-- Validate rollback to version 3
VALIDATE ROLLBACK TO VERSION 3;
-- Review validation report...
-- {
-- "canRollback": true,
-- "migrationsToReverse": [5, 4],
-- "downCommands": {
-- "5": ["DROP BUNDLE \"NewFeature\""],
-- "4": ["UPDATE BUNDLE \"Users\" REMOVE FIELD \"phone\""]
-- }
-- }
-- Validation passed, create backup first
BACKUP DATABASE "production" TO "prod_before_rollback.sdb";
-- Execute rollback
APPLY ROLLBACK TO VERSION 3;
-- Response: {
-- "status": "success",
-- "message": "Database rolled back to version 3 successfully",
-- "targetVersion": 3
-- }
-- Verify rollback
SHOW MIGRATIONS FOR "production";
-- Shows versions 4 and 5 now have Status = "ROLLED_BACK"
-- Current version: 3
-- Attempt rollback
APPLY ROLLBACK TO VERSION 2;
-- Error: rollback failed: DOWN command failed: cannot drop bundle "Users" - has relationships
-- Rollback failed! Database may be in inconsistent state
-- Recovery: Restore from backup
RESTORE DATABASE FROM "prod_before_rollback.sdb" AS "production-recovery";
-- Verify restored database
USE "production-recovery";
SHOW MIGRATIONS FOR "production-recovery";
-- Back to version 5 (pre-rollback state)
Runs a comprehensive 5-phase validation pipeline on a pending migration without executing it. This is a critical safety check before applying migrations.
VALIDATE MIGRATION WITH VERSION <number>
| Component | Description | Required |
|---|---|---|
| VERSION number | Version number of migration to validate | Yes |
-- Validate a pending migration
VALIDATE MIGRATION WITH VERSION 3
The validation runs 5 phases in sequence:
{
"status": "success",
"message": "Migration version 3 validation complete",
"report": {
"migrationVersion": 3,
"validatedAt": "2024-01-15T10:30:00Z",
"validatedBy": "system",
"syntaxPhase": {
"passed": true,
"errors": []
},
"semanticPhase": {
"passed": true,
"errors": []
},
"constraintPhase": {
"passed": true,
"errors": []
},
"performancePhase": {
"passed": true,
"warnings": [],
"estimatedDuration": "0.5s",
"commandCount": 5
},
"reversibilityPhase": {
"passed": true,
"warnings": [],
"downCommandsGenerated": true
},
"overallResult": "PASS",
"canApply": true,
"canApplyWithForce": true
}
}
| Result | Meaning | Action |
|---|---|---|
| PASS | All phases passed, no warnings | Safe to apply |
| PASS_WITH_WARNINGS | All blocking phases passed, warnings exist | Can apply with FORCE |
| FAIL | One or more blocking phases failed | Fix errors before applying |
| Error | Cause | Solution |
|---|---|---|
no active database |
No database selected | Use USE "database" first |
migration not found |
Invalid version number | Use SHOW MIGRATIONS to see versions |
migration not in PENDING state |
Already applied or failed | Only pending migrations can be validated |
DO:
DON'T:
-- Switch to database
USE "production";
-- Create migration
START MIGRATION WITH DESCRIPTION "Add product reviews"
CREATE BUNDLE "Reviews" WITH FIELDS (
{"id", STRING, true, true},
{"product_id", STRING, true, false},
{"user_id", STRING, true, false},
{"rating", INTEGER, true, false},
{"comment", TEXT, false, false},
{"created_at", DATETIME, true, false}
);
UPDATE BUNDLE "Products"
ADD RELATIONSHIP "product_reviews"
FROM BUNDLE "Products" TO BUNDLE "Reviews";
CREATE INDEX HASH ON BUNDLE "Reviews" WITH FIELD "product_id";
COMMIT
-- Validation returns version 3
-- Validate before applying
VALIDATE MIGRATION WITH VERSION 3;
-- Response shows all phases passed:
-- {
-- "overallResult": "PASS",
-- "canApply": true,
-- "syntaxPhase": {"passed": true},
-- "semanticPhase": {"passed": true},
-- "constraintPhase": {"passed": true},
-- "performancePhase": {
-- "passed": true,
-- "estimatedDuration": "0.3s",
-- "commandCount": 3
-- },
-- "reversibilityPhase": {
-- "passed": true,
-- "downCommandsGenerated": true
-- }
-- }
-- Validation passed - safe to apply
APPLY MIGRATION WITH VERSION 3;
-- Create migration with error
START MIGRATION WITH DESCRIPTION "Add user ratings"
UPDATE BUNDLE "Users"
ADD FIELD {"rating", INTEGER, true, false};
-- Error: NonexistentBundle doesn't exist
UPDATE BUNDLE "NonexistentBundle"
ADD FIELD {"test", STRING, false, false};
COMMIT
-- Validate migration
VALIDATE MIGRATION WITH VERSION 4;
-- Response shows semantic phase failure:
-- {
-- "overallResult": "FAIL",
-- "canApply": false,
-- "syntaxPhase": {"passed": true},
-- "semanticPhase": {
-- "passed": false,
-- "errors": [
-- "Bundle 'NonexistentBundle' does not exist"
-- ]
-- }
-- }
-- Cannot apply - must fix migration first
-- Create migration with many commands
START MIGRATION WITH DESCRIPTION "Import 500 seed records"
ADD DOCUMENT TO BUNDLE "Products" WITH VALUES (...);
ADD DOCUMENT TO BUNDLE "Products" WITH VALUES (...);
-- ... 498 more ADD DOCUMENT commands ...
COMMIT
-- Validate migration
VALIDATE MIGRATION WITH VERSION 5;
-- Response shows performance warning:
-- {
-- "overallResult": "PASS_WITH_WARNINGS",
-- "canApply": false,
-- "canApplyWithForce": true,
-- "performancePhase": {
-- "passed": false,
-- "warnings": [
-- "Migration contains 500 commands, exceeds threshold of 1000",
-- "Estimated execution time 2.5s exceeds threshold of 1.0s"
-- ],
-- "estimatedDuration": "2.5s",
-- "commandCount": 500
-- }
-- }
-- Can apply with FORCE if performance is acceptable
APPLY MIGRATION WITH VERSION 5 FORCE;
Simulates a rollback operation without executing it to verify it can be safely performed. This is critical before running APPLY ROLLBACK.
VALIDATE ROLLBACK TO VERSION <number>
| Component | Description | Required |
|---|---|---|
| VERSION number | Target version to validate rollback to | Yes |
-- Validate rollback from current version to version 3
VALIDATE ROLLBACK TO VERSION 3
The validation checks:
{
"status": "success",
"message": "Rollback to version 3 validation complete",
"targetVersion": 3,
"report": {
"canRollback": true,
"currentVersion": 5,
"targetVersion": 3,
"migrationsToReverse": [5, 4],
"downCommands": {
"5": [
"DROP BUNDLE \"NewFeature\"",
"UPDATE BUNDLE \"Users\" REMOVE FIELD \"preferences\""
],
"4": [
"UPDATE BUNDLE \"Users\" REMOVE FIELD \"phone\""
]
},
"dataImpact": {
"bundlesDropped": ["NewFeature"],
"fieldsRemoved": ["Users.preferences", "Users.phone"],
"estimatedDataLoss": "Documents in NewFeature bundle will be deleted"
},
"warnings": [],
"errors": []
}
}
The report includes:
| Field | Description |
|---|---|
| canRollback | Whether rollback is possible |
| migrationsToReverse | List of versions that will be rolled back |
| downCommands | DOWN commands for each migration |
| dataImpact | Estimate of data that will be lost |
| warnings | Non-blocking issues |
| errors | Blocking issues that prevent rollback |
The validation estimates potential data loss:
| Error | Cause | Solution |
|---|---|---|
no active database |
No database selected | Use USE "database" first |
invalid target version |
Target >= current version | Can only rollback to lower version |
missing DOWN commands |
Migration lacks DOWN commands | Manually create DOWN commands |
DOWN command validation failed |
DOWN commands are invalid | Review and fix DOWN commands |
DO:
DON'T:
-- Switch to database
USE "production";
-- Check current state
SHOW MIGRATIONS FOR "production";
-- Current version: 5
-- Validate rollback to version 3
VALIDATE ROLLBACK TO VERSION 3;
-- Response shows validation details:
-- {
-- "canRollback": true,
-- "currentVersion": 5,
-- "targetVersion": 3,
-- "migrationsToReverse": [5, 4],
--
-- "downCommands": {
-- "5": ["DROP BUNDLE \"Features\""],
-- "4": ["UPDATE BUNDLE \"Users\" REMOVE FIELD \"phone\""]
-- },
--
-- "dataImpact": {
-- "bundlesDropped": ["Features"],
-- "fieldsRemoved": ["Users.phone"],
-- "estimatedDataLoss": "All documents in Features bundle (approx 150 records), phone field data from Users"
-- },
--
-- "warnings": [
-- "Rollback will delete Features bundle and all its documents"
-- ]
-- }
-- Review data impact - acceptable for this scenario
-- Create backup before rollback
BACKUP DATABASE "production" TO "prod_before_rollback_v3.sdb";
-- Execute rollback
APPLY ROLLBACK TO VERSION 3;
-- Validate rollback
VALIDATE ROLLBACK TO VERSION 2;
-- Response shows cannot rollback:
-- {
-- "canRollback": false,
-- "errors": [
-- "Migration version 3 is missing DOWN commands",
-- "Cannot auto-generate DOWN for irreversible operation: DROP BUNDLE \"ImportantData\" WITH FORCE"
-- ]
-- }
-- Rollback not possible - would need to manually create DOWN commands
-- or accept that version 3 cannot be reversed
Last updated: March 2026