Watch replay now
  • eBook

Migration guide from Contentful to Hygraph

It’s easier than you think to migrate from Contentful to Hygraph. Here’s your step-by-step guide.

Christopher Kühn

Last updated by Christopher 

Mar 23, 2026

Originally written by Christopher

Mobile image

Beyond writing the perfect content and blog posts for your platform, beyond choosing the best images to compliment them, selecting the right CMS with which you store and access this data is also an important decision.

Contentful is a well-established name in the headless CMS space, having been around for quite some time. Undoubtedly, Contentful is great for basic content management. However, it also lacks certain features that could improve your application's performance and overall development experience.

There are several reasons why Contentful might not be the best choice for everyone. For one, its interface is quite unfriendly, and figuring out how to use it might be difficult, especially for people who have never used a headless CMS platform before.

Additionally, Contentful struggles with scalability and integration. You cannot customize where your data is hosted, which can lead to increased latency, affecting the speed at which data reaches your users. And although Contentful allows content access via GraphQL queries, it doesn't support GraphQL mutations. This limitation means you can't dynamically create new content or make changes to existing ones when integrating GraphQL.

contentful mutation

Moreover, Contentful's GraphQL requests are limited to 8 KB, which can be a major drawback if your application needs to handle large GraphQL requests. On top of these issues, Contentful's pricing structure can be unpredictable.

If you’ve decided to move on from Contentful and invest in a more powerful CMS like Hygraph, this ebook will guide you through the entire migration process, answering key questions and helping you navigate each step with confidence.

#Basics of website content migration

Website content migration is the process of moving digital content, like text, images, videos, and structured data, from one CMS or platform to another. A migration process should be planned and executed carefully; if not done properly, it can result in issues like data loss, broken links. This guide aims to help technical teams plan and execute a smooth migration. There can be several reasons a firm might need to migrate its projects, for example:

  • Traditional CMS to Headless CMS
  • Restructuring Schema & Data Models
  • Better performance
  • More flexible and developer/user-friendly platform
  • Rebranding or redesigning a website
  • Cost Efficiency

There are several types of content migration, including:

CMS-to-CMS: Moving content from one CMS to another of the same type, for example, Contentful to Hygraph, while preserving structure and functionality.

Platform-to-Platform: Transitioning content between different digital platforms, such as moving from a traditional CMS to a headless CMS.

Redesign: Updating the fundamental data models and architecture of the content, or due to redesigning/rebranding.

#Planning the content migration 

In this guide, we will see step-by-step how to migrate a CMS with the help of an in-depth example where we move data from Contentful to Hygraph. As a developer, it is important to understand the main concepts of both systems before starting to migrate the data, for example - what is the basic nomenclature Contentful has Content Types, while Hygraph calls the same thing Models.

Digging into the developer docs of both platforms is super helpful early on. It gives us a clear picture of how content is structured, how relationships between entries are handled, and how each system deals with media assets. It’s also a good idea to explore their APIs—spin up a test project, make a few requests, and get familiar with the request-response formats. This kind of prep work goes a long way in preventing surprises later in the migration process. For reference, here is the developer documentation for Contentful, and here is the documentation of Hygraph.

We will walk through an end-to-end example to see how we can plan website content migration. We will set up a Contentful project, create corresponding schema/models in a Hygraph project, navigate through Contentful and Hygraph APIs, and create an intermediate backend service that will migrate our CMS content from Contentful to Hygraph.

#Contentful to Hygraph migration

Contentful Project

We will keep this example pretty simple - Author & Blog Posts. Here’s how the content types inside Contentful should look with some dummy content. If you already have a contentful project and data ready to migrate, you can skip this section:

Author

  • name
  • email
  • bio
  • avatar - reference to an image
Contentful Projec

Setting up a Hygraph project

To migrate our Content from Contentful to Hygraph, first, we will set up our models inside Hygraph. If you do not have a Hygraph project yet, you can set it up here for free and read the guide on Hygraph models here.

Go to your project and create two models in the Hygraph dashboard: Author and Article, as shown below. This Hygraph schema model is based on our content types in Contentful. 

Schema → Models → Add

hygraph project - article

Since we have a simple example, we created these models from the UI. In production, you might have hundreds of different models and it’s best to use Hygraph SDK to programmatically create these data models. This way, you can have a trace of what’s happening safely stored in your codebase, and also replicate the entire setup very easily in any other Hygraph project.

hygraph schema - author

Migration API

Now, to migrate our data from Contentful to Hygraph, we will build a backend API. This API will move all the assets, authors, and article data, and also preserve the relationships between the records. Let us start by creating a very basic REST API with the help of Node.js and Express.

main.ts

Migration API

routes/migrate.routes.ts

routes:migrate.routes.ts

controllers/migrate.controller.ts

controllers:migrate.controller.ts

services/contentful-to-hygraph.service.ts

services:contentful-to-hygraph.service.ts

Okay, so this basic boilerplate code will set up a REST API with a route /migrate/contentful-to-hygraph. We have services and controllers set up that respond with a simple Hello World for now.

For the migration, we can see from our data in Contentful that we will need a way to export the following:

assetsauthor recordarticle record

Our migration logic is pretty simple - Migrate Assets first as they are not dependent on anything, and manage an IdMapping object for each content type/model migrated, so we can use them for defining relationships for the dependent records like Author and Articles. Something like:

migration api

We will build two new services - contentful.service.ts and hygraph.service.ts. The contentful service will help us pull the data from Contentful, and the hygraph service will push the data to our Hygraph project we set up earlier. Our contentful-to-hygraph.service.ts will use both of the above services and orchestrate the flow of code. Organizing this way will keep our code clean and easy to expand for future requirements.

Building Contentful service

Contentful API documentation provides all the required details for fetching data from Contentful. It supports a REST API as well as a GraphQL API. We will use Contentful’s Content Delivery Rest API  to get our data. The base URL follows this structure

https://cdn.contentful.com/spaces/{SPACE_ID}/environments/{ENVIRONMENT_ID}

Content can be retrieved via the entries endpoint, for example 

${baseUrl}/entries?content_type=author

→ Retrieves entries of the content type author

${baseUrl}/entries?content_type=blogPage

→ Retrieves entries of the content type blogPage

Assets can be retrieved via the assets

${baseUrl}/assets

→ Returns media assets like images and documents.

To call the Contentful API, we need three key pieces of information

  • SPACE_ID: Identifies your Contentful project.
  • ENVIRONMENT_ID: Typically master or develop/staging/uat if you have them.
  • ACCESS_TOKEN: A bearer token used to authenticate requests.

This can be found in the Contentful dashboard → Space Settings.

To encapsulate our logic, we define a ContentfulService class. This class will contain:

  • A reusable private fetchData() method.
  • Public methods like getAuthors(), getArticles(), and getAssets()

To understand Contentful’s API Request-Response structures, let us see a GET request to fetch Author list.

Request

https://cdn.contentful.com/spaces/{{space_id}}/environments/{{environment}}/entries?content_type=author&select=sys.id,fields&include=0

Response

Contentful’s API Request-Response

We can see our fields to migrate in the response structure. We have a sys.id for the unique identifier of a record, and an avatar.sys.id for the linking of an avatar to an author. Let us build our service now.

contentful.service.ts

contentful.service.ts

To work with Contentful in a clean, reusable way, we start by setting up a ContentfulService class. We use environment variables to keep credentials out of the codebase and make things configurable per environment. This skeleton sets up a centralized service for fetching Contentful data. The private fetchData() method will handle the actual HTTP call, while public methods like getAuthors(), getArticles(), and getAssets() just pass in the correct endpoint. 

Let us wrap up this service code. 

contentful service code

In the final part, we implement the fetchData() method, which is the core of our service. It takes an endpoint string, builds the full API URL using the CONTENTFULURL, CONTENTFULSPACEID, and CONTENTFULENVIRONMENT, and performs a GET request using Axios. This method handles the API call, checks for errors, and returns the fetched data or logs an error message if something goes wrong.

The public methods like getAuthors(), getArticles(), and getAssets() are simple wrappers around fetchData(). They pass the appropriate endpoint as an argument, allowing us to reuse the same logic to fetch different types of content.

Building Hygraph service

Hygraph has a powerful and flexible GraphQL API. If you are new to using GraphQL, you can read more about it here. We will use graphql-request - a minimal GraphQL client to make our API requests. Let us start by creating some types and building a Hygraph service that initiates a GraphQL client to interact with the Hygraph API endpoint. 

types.ts

types.ts

hygraph.service.ts

hygraph.service.ts

Next, let us add a method to upload assets.

hygraph.service.ts

hygraph upload assets

To interact with Hygraph, we're using graphql-request—a lightweight GraphQL client that's easy to set up and works great for small services like this. 

First, we define a few TypeScript interfaces (HygraphAsset, HygraphAuthor, and HygraphArticle) to keep our data structured and typesafe. 

Then, we build the HygraphService class, which initializes a GraphQL client using the Hygraph API URL and token from our environment variables. The uploadAssets() method takes an array of assets, loops through them, and sends each one to Hygraph using a mutation. It tracks which Contentful asset IDs map to their new Hygraph IDs so we can reconnect relationships later—simple, clean, and ready to scale.

In createAuthors(), we loop through each author object, format the GraphQL input (including connecting the avatar image if available), and run the mutation. We collect a mapping of the original Contentful IDs to the new Hygraph IDs so we can reference them later when creating blog posts.

The createArticles() method works the same way—it builds the input for each article, connects the related cover image and author, and fires off a mutation to create the record in Hygraph. Like before, we track the mapping of Contentful IDs to Hygraph IDs for relationship handling.

Here is the final hygraph.service.ts file:

hygraph.service.ts

Overall, this service abstracts all our interactions with the Hygraph GraphQL API, keeping things organized. It cleanly separates uploading media, creating authors, and creating articles, while preserving the links between them using ID mappings. 

Building the migration service

Finally, let us update our original migration service. It will orchestrate the migration using the Contentful and Hygraph services we built above. The migrateCMSData() method is the entry point called from the controller. It will invoke each sub-migration method in the right order—assets first, then authors, then articles. Each method will handle the fetching, transforming, and saving of that specific type of content. We will use the intermediate contentful-hygraph ID mappings for preserving relationships between content entries. 

contentful-to-hygraph.service.ts

contentful-to-hygraph.service.ts

Next, let us build the individual migration methods

Assets

assets - individual migration methods

This method fetches all assets from Contentful, transforms them into the format expected by Hygraph, and uploads them. It returns a mapping of original asset IDs to newly created Hygraph asset IDs, which will be used for linking assets to authors or articles.

Authors

authors - individual migration methods

In this method, authors from Contentful are fetched and transformed. If an author has an avatar, it's linked using the assetIdMapping generated earlier. The authors are then created in Hygraph, and a new ID mapping is returned for later use with articles.

Articles

articles - individual migration methods

Finally, articles are fetched, transformed, and linked to the appropriate cover images and authors using the previously built ID maps. The result is a complete and relational set of articles migrated into Hygraph.

Here’s the final service code:

contentful-to-hygraph.service.ts

contentful-to-hygraph.service.ts

Final Results

Our code is ready. Once we hit the API endpoint of our migration service, we can see our migration is successful, and the data has been successfully migrated from Contentful to Hygraph. Here are the final results from the Hygraph dashboard.

#Best practices for successful content migration 

Scalability

We have successfully migrated all assets and content records while maintaining the relationships between different models. Now, let’s touch on scalability. In our example, we used in-memory IdMapping objects to track linked content. This works fine for smaller datasets, but if you're dealing with millions of records or deeply nested relationships, you’ll hit memory limits fast. For large-scale migrations, you might want to consider more robust strategies, like processing entries one at a time, syncing related entities in one go as needed, or even using queues or streaming pipelines to better manage the load and keep things efficient.

Backups and data integrity

Always backup your content, databases, and media before starting the migration. It’s your safety net — just in case something goes sideways, you’ll have a fallback and can avoid data loss.

Communication and collaboration

A successful migration isn't just about code. Clear communication between developers, content teams, and stakeholders is key. Set up a migration roadmap with clearly defined roles, responsibilities, and checkpoints. Keeping everyone in the loop with regular updates helps catch issues early and keeps the whole team aligned

Testing and validation

After the migration, you’ll notice all content in Hygraph is in Draft mode. Take this opportunity to double-check that everything looks right, whether that’s through manual review or automated tests. Once you're confident in the migrated data, proceed with publishing the content. A best practice is to roll out the new CMS behind a feature flag, allowing you to gradually expose it to users while ensuring production stability remains intact. You can also test in a staging environment to catch issues before going live.

#Why you should make the move to Hygraph

If you're looking for a modern CMS that is developer-friendly and can be very easily used by non-tech team members, Hygraph is a solid choice. It's a headless CMS that has been battle-tested in production by companies of all sizes, offering everything you'd expect from a platform built for flexibility, performance, and scalability. Take a look at our successful case studies for insights into how our customers are utilizing the platform. 

Here are some key features of Hygraph:

  • Headless by design: Your content is completely decoupled from how it’s presented. Build any frontend you want—React, Vue, mobile apps, whatever—and pull content via the API.

  • GraphQL APIs: Hygraph uses GraphQL out of the box, so you can avoid all the drawbacks that come with REST API like over-fetching/under-fetching, less flexibility, strong coupling between backend services and frontend views.

  • User experience: Hygraph has a clean user interface and a very intuitive user experience that makes it very easy for tech / non-tech users to adapt to the platform.

  • Built to scale: Whether you're managing a few pages or a massive multi-language site, Hygraph is optimized for performance and handles large content volumes.

  • Multi-tenancy: Manage multiple projects or environments under a single account—ideal for agencies or teams juggling multiple brands or regions.

  • Content federation: Need to pull data from external sources or APIs? Hygraph can aggregate content from other platforms, giving you a unified backend.

  • Granular permissions: Fine-tuned access control means you can define who can do what, keeping your content safe and organized.

  • Webhooks & integrations: Plug into your existing stack—eCommerce tools, analytics, marketing platforms, etc.—with built-in webhook and integration support.

Still using a traditional CMS? You may want to review our guide on selecting a headless CMS. It breaks down why making the switch makes sense and walks through some of the top options available today.

#Final words

To wrap things up, migrating content from one CMS to another can be challenging, but when done for the right reasons, it’s well worth the effort. A solid migration plan, including thorough research, reviewing documentation, testing extensively, taking backups, and maintaining close collaboration with your team, can make the entire process smoother and less risky. 

In this guide, we walked through a hands-on example of migrating content from Contentful to Hygraph using a custom Migration API. If you’re planning a move, using a modern CMS like Hygraph can level up how you manage and deliver content in the long run.

#About Hygraph

Hygraph is the first GraphQL-native Headless Content Platform, enabling teams across the world to rapidly build and deliver tomorrow’s multi-channel digital experiences at scale.

It was designed for removing traditional content management pain points by using the power of GraphQL, and take the idea of a Headless CMS to the next level. Hygraph integrates with any frontend technology, such as React, Vue and Svelte.

Get started with Hygraph by creating a free account, learn how our customers are solving real-world problems, gather information about next-generation CMS from our resources or academy, or learn more about the applications of Hygraph.

Get started for free, or request a demo
to discuss larger projects