Migration Tracking
When you use the migration workflow, ctkit needs to know which migrations have already been applied. It tracks this inside Contentful itself — no external database or state file required.
How it works
Section titled “How it works”The first time you run ctkit migrate, ctkit creates a content type called ctkit_migration_history in your Contentful space. Each time a migration runs, a new entry is created in this content type recording what happened.
The content type is named ”🔄 ctkit migration history” in the Contentful UI and is marked as system-managed. You should not edit these entries by hand.
What gets recorded
Section titled “What gets recorded”Each migration record stores:
| Field | Type | Description |
|---|---|---|
migrationId | Symbol | Unique identifier, e.g. 20250702T143021_add_blog_fields. Validated as unique. |
filename | Symbol | The migration file name. |
executedAt | Date | When the migration was executed (ISO 8601). |
checksum | Symbol | SHA-256 hash of the migration file contents. |
executionTimeMs | Integer | How long the migration took in milliseconds. |
status | Symbol | Either success or failed. |
errorMessage | Text | Error details if the migration failed. Empty on success. |
description | Text | Human-readable summary of what the migration does. |
ctkitVersion | Symbol | The version of ctkit that executed the migration. |
environment | Symbol | The Contentful environment (development, staging, production, test). |
Checking migration status
Section titled “Checking migration status”ctkit statusThis reads from the ctkit_migration_history content type and shows:
- Which migrations have been executed (with timestamps)
- Which migrations are pending
- Whether any migrations failed
✓ success 20250702T121925_crystal_lion_hammer (2 hours ago)✓ success 20250702T143021_add_blog_fields (1 hour ago)⏳ pending 20250703T091500_add_categories
2 executed, 1 pending, 0 failedChecksum verification
Section titled “Checksum verification”Every migration file is hashed with SHA-256 when it’s executed. The hash is stored in the migration record.
This serves as a tamper detection mechanism: if a migration file is modified after it was executed, ctkit can detect the mismatch. This prevents scenarios where someone edits an already-applied migration, creating an inconsistency between what the migration history says happened and what the file currently contains.
Failed migrations
Section titled “Failed migrations”When a migration fails, ctkit records the failure with:
status: "failed"- The error message
- The execution time up to the point of failure
Failed migrations are not automatically retried. To retry a failed migration after fixing the issue:
ctkit migrate --forceThe --force flag tells ctkit to re-run migrations that were previously recorded (including failed ones), rather than skipping them.
Manual inspection
Section titled “Manual inspection”You can view migration history entries directly in the Contentful web UI:
- Open your Contentful space.
- Go to Content.
- Filter by content type: 🔄 ctkit migration history.
- Entries are ordered by
executedAt(most recent first).
This is useful for debugging, auditing, or understanding what happened in a specific environment.
Why track in Contentful?
Section titled “Why track in Contentful?”Storing migration history inside Contentful itself means:
- No external state — no database, no S3 bucket, no lock file to manage.
- Environment-aware — each Contentful environment has its own migration history. You can see exactly what’s been applied to
stagingvs.production. - Portable — anyone with access to the Contentful space can inspect migration status. No tooling required beyond the Contentful UI.
- Cloneable — when you clone a Contentful environment, the migration history comes with it.