• Cheat sheets
  • Documentation
  • API reference
  • Product updates
  • Sign in
Kontent.ai Learn
  • Plan
  • Set up
  • Model
  • Develop
  • Create
  • Overview
    • Overview
      • Overview
      • Create migration scripts
        • When to use migration scripts
        • The building blocks of content migration
        • Before you start
        • Example content migration scenario
        • Create a migration script
        • Write a rollback function
        • Keep your scripts maintainable
        • Run your scripts safely
      • Safe content migration practices

Create migration scripts with data-ops

Tomas Dvorak
6 minutes
0% complete
Changing your content model often means updating existing content to match the new structure. Migration scripts help you automate content changes across your project so you can update items in bulk without manually changing them through the Management API. This lesson walks you through creating migration scripts with data-ops.

When to use migration scripts

Migration scripts help you automate content transformations across your Kontent.ai project. Reach for one whenever you need to:
  • Update content items after making changes to your content model
  • Bulk-update element values across many items at once
  • Restructure content from one content type to an updated one
  • Apply consistent changes across language variants
  • Transform content as part of an environment sync or deployment workflow
For importing content from an external system instead, see Migrate from other systems.

The building blocks of content migration

When migrating content within Kontent.ai, you’re working with:
  • Source – the existing content in your Kontent.ai environment that needs to be updated
  • Migration logic – the rules and operations that define how content should be modified
  • Destination – the Kontent.ai environment where the transformed content will be saved
The data-ops migrations command provides a framework for writing and executing these migration scripts programmatically.

Before you start

Make sure you have the following ready:
  • Node.js (LTS version)
  • The data-ops package – run it directly with npx (as shown in the example below) or install it locally
Once you have these ready, you can create your first migration script.

Example content migration scenario

Let’s say you have a project with blog articles. Each article has an author typed manually as “Jane Doe” into a text element. At some point, you decide to include additional information about the authors, such as their bios and profile images. Because adding these details to each article would take a long time and be hard to keep in sync, you create a new content type called Author. Then you link the Author content items to the articles. The example script below covers only the first part of that change, creating the Author type with a name and a bio. Any other element, such as one for the profile image, is added the same way.

Create a migration script

To automate a content change, start by creating a migration script. The migrations add command generates a Kontent.ai migration script file. The generated script contains a module object with three properties:
  • order – a unique number or date that determines execution sequence, with number-based ordering always running before date-based. By default, migrations add creates each migration file with order: 1, so assign a unique order value before running the migration.
  • run – the function that performs the migration, using the Management SDK client passed in as a parameter (named apiClient in the generated script).
  • rollback (optional) – the function that reverses the migration, if you need to undo it later.
Add --timestamp to migrations add to name the file with the current UTC date and time, and set order to that same value, ensuring each new script has a unique order value assigned automatically.
For example, to create a migration script named my-first-migration, run:
Shell
npx @kontent-ai/data-ops@latest migrations add \
  --migrationsFolder my-first-migration \
  --name my-first-migration \
  --type js
This generates a JavaScript file:
JavaScript
const migration = {
  order: 1,
  run: async apiClient => {},
  rollback: async apiClient => {},
};

export default migration;
Without --type js in the command, migrations add generates TypeScript instead (the CLI’s default). Keep in mind migrations run only ever executes JavaScript, so a .ts migration needs to be transpiled into ES Modules with your own TypeScript setup before you can run it.
Now, let’s put something inside that empty run function. For the scenario above, that means creating the Author type and its elements:
JavaScript
run: async apiClient => {
  await apiClient
    .addContentType()
    .withData(() => ({
      name: "Author",
      elements: [
        { name: "Name", type: "text" },
        { name: "Bio", type: "rich_text" },
      ],
    }))
    .toPromise();
},

Write a rollback function

The rollback function reverses whatever run did, so you have a way back if a migration turns out wrong. For the Author type from the example above, that means deleting it:
JavaScript
rollback: async apiClient => {
  await apiClient
    .deleteContentType()
    .byTypeCodename("author")
    .toPromise()
    .catch(e => console.log(`Unsuccessful deletion of type Author: ${e}`));
},
Notice the .catch() at the end. It’s a good idea to wrap deletions like this so the rollback still completes even if the original migration only got partway through. Without it, trying to delete something that was never created would cause the whole rollback to fail right when you need it most.
An empty rollback function is valid, which means the migration runs and the rollback later completes without changing anything or reporting an error. You only discover it's empty when you need it, so write it together with run.

Keep your scripts maintainable

A few practices keep your scripts manageable as your migrations folder grows:
  • One script per task. It’s easier to tell where something failed when each script does one thing.
  • Hardcoded vs. dynamic values. For a one-off script, like updating one specific content item, hardcoding the values you’re changing works fine. For a script you’ll adapt or re-run against different content, it’s recommended to retrieve values dynamically by looking up the content types, items, or elements you need through the Management API at runtime, rather than hardcoding specific IDs or codenames into the script.
  • Commit migrations to version control. Treat them like database migrations, because the folder is your change history for the environment.

Run your scripts safely

You now have a migration script that creates the Author type, with a rollback that removes it.Your scripts don’t change anything until you run them. Running them is covered in a separate lesson on purpose. A migration pointed at the wrong environment changes live content immediately, and the only way to undo it is the rollback function you wrote.Continue with Safe content migrations in production to execute them, starting in a non-production environment, validating against a fresh copy of production, and only then touching production itself.
Sign in with your Kontent.ai credentials or sign up for free to unlock the full lesson, track your progress, and access exclusive expert insights and tips!
Sign in
Copyright © 2026 Kontent.ai. All rights reserved.
  • Web
  • Privacy policy
  • Cookies policy
  • Consent settings
  • Security
  • GDPR