How to Carry Out a Successful Contentful Migration?

Sahil Mahalley

Blog / How to Carry Out a Successful Contentful Migration

Moving your content to Contentful is like relocating to a new house: it's an opportunity to correct what went wrong previously and position yourself for the future.

Why make the switch? Perhaps you want to escape from outdated, cumbersome systems, consolidate all your content in one location, or simplify sharing content between devices and channels.

But like moving home, it's not all good. You'll have to be careful not to lose data, disrupt workflows, or have the same issues in a new system.

Before you dive into the execution of your Contentful migration for your current content, there are a few things you need to attend to.

Preparing for Contentful Migration

Auditing Your Content

Start by taking stock of everything you have. How much content is there? What’s actually useful? Maybe old blog posts can stay, but outdated product pages should go.

This is also your chance to fix past mistakes, like messy SEO tags or slow editorial processes, and align your content with new goals.

Designing Your New Content Model

Based on your audit, decide how content will be organized in Contentful.

For example, if your old system forced writers to jump through hoops to add images, simplify it. Balance what editors need (easy-to-use fields) with what developers need (clean, reusable data).

Image: Contentful Content Model Editor

Choosing Your Approach for the Migration in Contentful CMS

You can either:

  1. Lift-and-shift: Move everything as-is. Quicker, but you’ll still need to adjust things to fit Contentful.
     
  2. Reinvent: Start fresh. Fix old issues and redesign your content structure.

Both require planning. The key is to involve everyone—editors, developers, designers—so your new system works for the whole team.

Fundamental Stages of Contentful Migration

Here, I am sharing with you the steps of Contentful Migration. However, these are the basic steps. If you already have an idea you can skip to the actual technical implementation.

Image: Migrating Content to Contentful

  1. Export Your Content: Get your data out of the old CMS. How? It depends on your current platform—some have built-in tools, and others might need custom scripts.
     
  2. Map Fields to Contentful: Match old content fields to new ones. For example, an “Author” field in your old system might become a “Contributor” reference in Contentful.
     
  3. Test Migration Scripts: Use Contentful’s CLI (command-line tool) to write scripts that automate moving data. Test these in a safe, isolated environment (like one called `feature-1`) to avoid breaking live content.
     
  4. Move-in Batches: Don’t migrate everything at once. Do small chunks, check for errors, and fix as you go.

Tools You’ll Need

  1. Contentful CLI: It lets you run scripts to create content types or update entries.
     
  2. `makeRequest`: A tool in scripts to fetch data from Contentful’s API (like grabbing details from a linked entry).

Image: Migration Tools and their Roles

Technical Implementation of Contentful Migration

Well, now that we’ve gone through the basic steps, let’s jump to how you will be writing scripts and building your logic bit-by-bit to implement the same process. I’ve also included code snippets so that you can take their help to customize your scripts

Writing Scripts to Implement Step-by-Step Contentful Migration

Step 1: Set Up Your Playground

You need a safe space to test scripts without breaking live content.

# Install the CLI 
npm install -g contentful-cli  

# Log in & pick your Contentful "workspace"  
contentful login  
contentful space use "your-space-id"  

# Create a test environment (like a sandbox)  
contentful space environment create --name "feature-1"  

Step 2: Start Your Script File

All migrations begin with this basic structure.

// File: my-migration.js  
module.exports = function (migration, { makeRequest }) {  
 // Your code goes here! ↓  
}; 
  • 'migration': Lets you edit content types and entries.
  • 'makeRequest': Fetches data from Contentful's API.  

Step 3: Update Content Types

To add/remove fields in your content model.

// Edit the "blogpost" content type  
const blogpost = migration.editContentType('blogpost');  

// Add a new image field  
blogpost  
  .createField('mainImage')  
  .name('Main Photo')  
  .type('Link')  
  .linkType('Asset');

Step 4: Add Rules to Fields

Ensure only valid data gets through (e.g., only images).

.validations([  
  { 'linkMimetypeGroup': ['image'] } // Allow images ONLY  
]); 

Step 5: Move Data Between Fields

Copy old content into new fields.

migration.transformEntries({  
  contentType: 'blogpost',  
  from: ['oldImage'], // Old field  
  to: ['mainImage'],  // New field  
  transformEntryForLocale: async (from, currentLocale) => {  
    // Skip if no image exists  
    if (!from.oldImage) return;  
    // Copy the image over  
    return { mainImage: from.oldImage[currentLocale] };  
  }  
});

Step 6: Tidy Up Old Fields 

Avoid confusion by hiding/deleting unused fields.

 // Hide the old field from editors  
blogpost.editField('oldImage').disabled(true);  

// OR delete it permanently  
blogpost.deleteField('oldImage');

Step 7: Run & Test Your Script 

Test in your sandbox before touching real content.

contentful space migration --environment-id 'feature-1' my-migration.js   

The Complete Contentful Migration Script

Here’s a template of the complete script that you can use for Contentful migration. Of course, you can make the changes according to what suits you best.

.createField('mainImage')
.name('Main Image')
.type('Link')
.linkType('Asset')
.validations([
            {
                'linkMimetypeGroup': ['image']
            }
        ]);

  
    // Transform existing entries to match new structure
    migration.transformEntries({
        contentType: 'blogpost',
        from: ['image'],
        to: ['mainImage'],
        transformEntryForLocale: async (from, currentLocale) => {
            // Skip empty entries
            if (!from.image) {
                return;
            }

            // Get the ID of the linked image entry
            const imageEntryId = from.image[currentLocale].sys.id;

            try {
                // Fetch the linked image entry
                const imageEntry = await makeRequest({
                    method: 'GET',
                    url: `/entries/${imageEntryId}`
                });

                // Return the transformed data
                return {
                    mainImage: imageEntry.fields['image'][currentLocale]
                };
            } catch (error) {
                console.error(`Error processing entry ${imageEntryId}:`, error);
                return null;
            }
        }
    });

    // Disable old field after migration
    blogpost.editField('image').disabled(true);
};

Testing Safely

Always test scripts in a new environment (like `feature-1`) first. Once everything works, “go live” by pointing your main environment to the updated one—like flipping a switch.

Image: Contentful's Environment Settings

Advanced Contentful Migration Strategies

Handling Tricky Schema Changes during Contentful Migration

Suppose you need to add a new value to a dropdown list (such as adding "RPG" to a list of game types). In Contentful, you can't simply append the new value—you must rewrite the whole list of permitted values.

This creates issues if another person is modifying the same list simultaneously. For instance, if you include "RPG" and another programmer includes "Tower Defense", whoever executes their script last will overwrite the other person's work.

module.exports = function (migration) {  
  const rules = migration.editContentType("rules");  
  const gameType = rules.editField("gameType");  
  gameType.validations([  
    { in: ["Casino", "Other", "Solitaire", "Trick Taking", "Rummy", "RPG"] }  
  ]);  
};

Another headache: Contentful doesn’t let you check the current schema during migrations. You can’t say, “Hey, what’s already here? Let me adjust that.” Instead, you have to hardcode every change, which risks breaking existing validations or losing data.

Tracking the Contentful Migrations

Contentful doesn't keep track of which migrations you've already run. If you accidentally rerun a script, it could break or—perish the thought—corrupt your content.

To avoid this, some people use custom plugins to log that migrations have already been applied. It's akin to leaving crumbs so you can avoid retracing your steps.

# Example using a custom script to track migrations  
contentful-migrations up-- path contentful/migrations

Overcoming the Challenges in Contentful Migration

Common Mistakes

  • Scripts That Break on Replay: If migration isn’t designed to run safely multiple times (idempotent), rerunning it could delete data or duplicate fields.
  • Conflicting Changes: Two developers editing the same dropdown list? The last one to merge their code “wins,” and the other’s changes vanish.

How to Fix It

  • Test in a Sandbox: Always test migrations in a separate environment (like `feature-1`) first. Think of it as a rehearsal space.
  • Automate Checks: Use CI/CD pipelines (automated workflows) to run migrations only once and flag conflicts early.

Things to Take Care of Post Your Contentful Migration

Double-Check Everything

  • Spot-check migrated content: Are images broken? Do links work?
  • Update apps or websites that pull data from Contentful to match the new content model.

Clean Up Old Fields, Post the Contentful Migration

Once you’re sure the new system works, disable old fields (like `blogpost.image`) to avoid confusion. It’s like donating old furniture after a move—you don’t need it anymore.

blogpost.editField('image').disabled(true);

Keep Improving

Contentful migration isn’t a one-time fix. As your needs change, tweak your content model. Maybe add a new field for video embeds or simplify a clunky workflow.

Image: Post-Migration Checklist

Tools and Resources

  • Contentful’s Free Help's "Migrating to Contentful" course walks you through planning.
  • If you’re stuck, their Professional Services team can guide you, like hiring a moving coordinator for your content.
  • You can also use community tools and forums for additional help.

Your Contentful Migration Checklist: Done.

Migrating to Contentful might feel like packing up a decade’s worth of stuff into boxes—tedious, but worth it once you’re settled. The key?

Plan ahead, test often, and don’t be afraid to toss what you don’t need. Use scripts to automate the heavy lifting, lean on tools like the CLI or community libraries to avoid mistakes, and always keep improving after the move.

Sahil Mahalley
by Sahil Mahalley
Jr. Creative Content Writer

End Slow Growth. Put your Success on Steroids