Skip to content

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.

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.

Each migration record stores:

FieldTypeDescription
migrationIdSymbolUnique identifier, e.g. 20250702T143021_add_blog_fields. Validated as unique.
filenameSymbolThe migration file name.
executedAtDateWhen the migration was executed (ISO 8601).
checksumSymbolSHA-256 hash of the migration file contents.
executionTimeMsIntegerHow long the migration took in milliseconds.
statusSymbolEither success or failed.
errorMessageTextError details if the migration failed. Empty on success.
descriptionTextHuman-readable summary of what the migration does.
ctkitVersionSymbolThe version of ctkit that executed the migration.
environmentSymbolThe Contentful environment (development, staging, production, test).
Terminal window
ctkit status

This 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 failed

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.

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:

Terminal window
ctkit migrate --force

The --force flag tells ctkit to re-run migrations that were previously recorded (including failed ones), rather than skipping them.

You can view migration history entries directly in the Contentful web UI:

  1. Open your Contentful space.
  2. Go to Content.
  3. Filter by content type: 🔄 ctkit migration history.
  4. Entries are ordered by executedAt (most recent first).

This is useful for debugging, auditing, or understanding what happened in a specific environment.

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 staging vs. 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.