When Migrations Are Needed
Not every schema change requires a migration. MDCMS distinguishes between non-breaking changes (handled automatically) and breaking changes (requiring explicit migration).Non-Breaking Changes
For non-breaking changes, the standard schema sync workflow handles everything automatically:1
Update the schema
Modify your
mdcms.config.ts to add the new field, type, or environment.2
Sync to the server
Run
mdcms schema sync. The server computes the new schema hash and updates
the schemaRegistryEntries and schemaSyncs tables.3
Continue editing
Existing documents remain valid. New documents will include the updated
field definitions in the Studio editor.
Database Migrations
Database schema changes (adding tables, columns, or indexes to the PostgreSQL schema) are managed through Drizzle ORM’s migration toolkit.1
Modify the schema definition
Edit
apps/server/src/lib/db/schema.ts to add, modify, or remove table
definitions.2
Generate the migration SQL
Run the Drizzle migration generator:
bash cd apps/server bun run db:generate This produces a timestamped SQL migration file in the
migrations directory.3
Review the generated SQL
Always review the generated migration before applying it. Drizzle generates
SQL based on the diff between the current schema definition and the last
known state. Verify that destructive operations (column drops, type changes)
are intentional.
4
Apply the migration
Run the migration against the target database:
bash cd apps/server bun run db:migrate Content Migrations
Content migrations transform existing documents when the schema changes in a way that is incompatible with stored data. Themdcms migrate CLI command handles this process.
Preview Mode
By default,mdcms migrate generates a migration plan without applying it:
- Which documents are affected
- What transformations will be applied
- Whether any documents cannot be automatically migrated
Apply Mode
To execute the migration, add the--apply flag:
- Transforms each affected document’s frontmatter according to the migration rules
- Updates the draft state (
body,frontmatter,updatedAt,draftRevision) - Auto-publishes updated documents that were previously in a published state
- Records the migration in the
migrationstable (name, schema type, documents affected, who applied it, when)
Breaking Change Scenarios
The following scenarios require explicit content migrations.Type Rename
When renaming a content type (e.g.,Post to BlogPost):
- Add the new type to
mdcms.config.ts - Run
mdcms schema syncto register the new type - Run
mdcms migrate --applyto update all documents from the old type to the new type - Remove the old type from the config
- Run
mdcms schema syncagain to deregister the old type
Field Type Change
When changing a field’s type (e.g.,tags: z.string() to tags: z.array(z.string())):
- Update the field definition in
mdcms.config.ts - Run
mdcms schema sync - Run
mdcms migrateto preview the transformation (e.g., wrapping string values in arrays) - Run
mdcms migrate --applyto execute
Field Removal
When removing a field from a content type:- Remove the field from
mdcms.config.ts - Run
mdcms schema sync - Run
mdcms migrate --applyto clean the removed field from existing document frontmatter
Field removal migrations are optional but recommended. Documents with extra
frontmatter fields will not cause errors, but removing stale data keeps the
content store clean and reduces confusion in API responses.
Migration Records
Every applied migration is recorded in themigrations table:
This table provides an audit trail for all content transformations and can be queried to verify migration history.