Now booking enterprise content platform builds for 2026. Contact us

All articles Migrations

Migrating from Hygraph to Payload CMS: export, schema, and the federation layer

Hygraph has no dataset export command. The migration reads content back through the GraphQL Content API a page at a time, maps models and components onto Payload collections, and works out which content the federation layer never stored in the first place.


Hygraph is a Berlin company selling a GraphQL-native content platform with a federation layer on top, positioned at enterprise estates that pull content from several systems at once. That matters to European teams for a practical reason covered under assets below, and it is why the platform turns up on DACH shortlists more often than its overall market share suggests. That positioning shapes the exit. A migration off it is less about converting a proprietary rich-text format and more about two other questions: how you get content back out of an API that was designed for reading a page at a time, and what happens to the content that was never stored in Hygraph at all.

There is no dataset export command here. The Content API is the export, and its pagination limits set the shape of the work.

This guide covers the migration in the order it normally runs: read the schema, page the content out, decide what federation leaves behind, move assets, carry localised fields, import in two passes, and list what has to be rebuilt.

A note on searching for prior material. The platform launched in 2017 as GraphCMS and took its current name in 2022, in the same announcement that introduced content federation. The API still carries the old name in places, so the locale header is gcms-locales and assets are served from graphassets.com. Write-ups filed under GraphCMS describe an asset system and an upload API that Hygraph has since replaced. Both are covered below.

The order the work runs in

The work moves in a fixed order, because each step depends on the one before it.

The schema comes first, because the Payload collections have to exist before anything can be written into them. Assets come second, so that entries have media IDs to point at. Entries come third, imported with their source identifiers kept. References come fourth, resolved once every entry exists and has a Payload ID.

The federation layer sits outside that sequence. It is not content to be moved, and treating it as content is the mistake that makes a Hygraph migration quote wrong.

Read the schema before you read the content

A Hygraph schema is built from models, components and enumerations. Each maps somewhere different in Payload.

Models create standalone entries. Each one becomes a Payload collection.

Components do not. Hygraph documents them as a way to reuse a field structure, where each component instance stores its own content inside the entry that holds it. They are embedded, and they cannot be queried as independent entities. In Payload they land as groups, arrays or blocks depending on how the content is used. A basic component holds a single component type in a field, which usually maps to a group or an array. A modular component allows two or more component types in the same field, and that is the shape Payload’s blocks field is built for.

Enumerations map onto Payload select fields with the same option set.

One limit is worth knowing before the transform is planned. The Hygraph Studio interface shows up to 50 component instances per entry, and instances beyond that stay queryable through the API while being invisible in the UI. An entry that looks short in the editor can carry more than the editor shows, so the export should be trusted over the interface when the two disagree.

Page the content out through the Content API

Every model gets a generated singular query and a generated plural query, and the plural queries are how an export runs. The constraint is the page size.

Hygraph documents five pagination arguments: first, last, skip, before and after. For projects created after 14 June 2022 the default result size for a multi-entry query is 10, and the documented maximum for first or last is 100. Projects older than that date default to 100 with a maximum of 1000. So a collection of forty thousand entries is at least four hundred requests on a current project, and the export script has to be written to resume.

Cursor paging is the reliable way to do it. Hygraph follows the Relay cursor connection specification and exposes pageInfo with hasNextPage, hasPreviousPage, startCursor and endCursor, so a loop can carry endCursor into the next request’s after argument until hasNextPage goes false. Offset paging with skip works and drifts when content changes underneath a long run. One documented rule catches people out: first cannot be combined with before, and last cannot be combined with after.

Relations can be fetched in the same request. That is convenient, and it can be expensive. Hygraph’s own guidance is that deeply nested or complex relations may affect query performance and that queries should be tested against the project’s own workload. For an export, shallow reads plus a reference-resolution pass usually beat one deep query per entry.

What the federation layer leaves behind

Hygraph documents content federation as a way to integrate content from multiple systems and sources into the Hygraph API without migrating the content itself. A remote source is documented as a custom resolver entry point for the schema that allows data to be sourced from an external third-party web service. Remote fields enrich a model with external data, and top-level remote fields fetch remote data outside the context of any model. All of it resolves when the query runs.

Hygraph names four pieces in that architecture: the remote source itself, a custom type for content coming from it, a remote field that connects that data to an entry, and a cache.

The cache is the one to watch during an export. Queries that include remote fields are cached with a TTL of 15 minutes by default. The TTL can be overridden in the field’s settings down to a minimum of 60 seconds, and a cache-control header from the remote source overrides the Hygraph configuration entirely, which puts the staleness window partly outside the project’s control. Remote values arrive through the same query as stored content and look identical in the response, so a script that walks the schema without checking which types are custom will write another system’s cached data into Payload as though Hygraph had owned it.

None of that data is trapped. Product records, pricing, inventory or whatever else was federated still live in their own systems, exactly as they did before Hygraph was introduced. There is nothing to extract and nothing to lose.

The composition, though, was the product. What Hygraph provided was a single endpoint that presented several systems as one graph, and that endpoint disappears with the platform. A migration has to decide where composition happens afterwards. Payload holds the content it owns and the front end queries the other systems directly, or a separate layer is built to federate them again. That decision belongs in the scope before the quote, because it is engineering work that has nothing to do with moving entries.

Read the schema for remote sources and remote fields before sizing anything, and read it in the schema builder: a remote field whose visibility is set to API only never appears in the content form while staying queryable through the API. A project that federates heavily has less content to migrate than its schema suggests and more integration work than its content volume suggests.

Move assets, and check which system the project is on

Every Hygraph project includes an Asset model that cannot be deleted. It is localised by default and accepts any file type, including audio and archives. Assets are referenced from models through the Asset field type, and a model can hold a one-to-many reference to several of them.

Four asset queries are generated for every project: asset, assets, assetVersion and assetsConnection. The last is the one an export loop uses.

Getting a working file URL takes one extra step that is easy to miss. Hygraph’s own guidance is to fetch url and fileName and combine them manually or in a script, separated by a slash. The documentation’s own example resolves to a full address of the form https://eu-central-1-shared-euc1-02.graphassets.com/<environmentId>/<handle>/content-finder.gif. The file extension at the end has to match the current version of the asset, so a file converted to webp through URL transformations needs webp there.

Which asset system the project uses changes what you find. Projects created after February 2024 use Hygraph Asset Management and older projects used the Legacy asset system. The legacy URL form was media.graphassets.com/<transformations>/handle. The current form adds a regional subdomain, an environment identifier and the optional filename: <regional-subdomain>.graphassets.com/<environmentId>/<transformations>/handle/filename.jpg. The environment identifier is the asset config API key for that environment, readable through the Management API. The subdomain is regional, so a project hosted in the shared Germany region serves its media from eu-central-1-shared-euc1-02.graphassets.com. Where the current setup was chosen for EU data residency, that constraint follows the media into whatever storage the Payload build uses, and it belongs in the scope alongside the content itself.

Hygraph sunset the old asset domain after the end of June 2025, and the transitions it ran before that are why this needs auditing. When a project moved between the two systems, Hygraph rewrote asset URLs inside Markdown and Rich Text fields. It did not rewrite them inside Single Line, Multiple Line or JSON fields, and its own documentation tells project owners to go through those fields looking for media.graphassets.com and replace what they find. Any of those that were missed are dead addresses sitting in content that is about to be migrated, so grep the export for the legacy domain before importing anything.

Transformation coverage also differs between the systems. The legacy system natively supported resize and output. The current system documents resize, blur, border, compress, crop, quality, sharpen, auto_image and output, with file-type conversion limited to image mime types. Front-end code that builds transformation URLs by hand has to be rewritten for Payload regardless, since those URLs belong to Hygraph’s delivery layer and do not travel with the content.

Localisation is configured field by field

Hygraph localises at field level. A field is marked as localisable in the schema builder, and fields that are not marked return the same value in every locale. That is a different shape from systems that keep a whole entry per locale, and flattening it during export loses information that the Payload build then cannot reconstruct.

Two mechanisms read it back. The localizations field on an entry returns the locales that hold values, and passing includeCurrent: true includes the default locale in that list. The gcms-locales header accepts a list and returns locales in the order they are requested, from left to right, so the response comes back as a fallback chain.

Decide the Payload localisation strategy before the export script is written, because the two reads produce different files. An export that loops locale by locale through the header will quietly fill gaps with fallback values and record them as content.

Import in two passes

References between entries come out of the API as related objects or identifiers that mean nothing in Payload until the target exists. The reliable sequence is the same one that works on any structured-source migration.

Import every entry first, with its Hygraph identifier written into a field the Payload config keeps for the purpose. Then run a second pass that walks the same data, looks up each reference by that stored identifier, and writes the Payload relationship. Assets are already in place from the earlier step, so upload fields can resolve in the first pass.

Keep the identifier field after cutover for as long as anything still needs reconciling against the old system.

What does not export

The Content API returns content. Everything else in the project is rebuilt.

Schema definitions do not become Payload collection configs. Remote sources and remote fields are integrations, and they get re-implemented wherever composition lands. Permissions, roles and publishing workflows are configuration in Hygraph and configuration again in Payload. Webhooks are re-pointed. Anything a front end does with Hygraph delivery features, including asset transformation URLs and locale headers, becomes application code on the new stack.

Upload state is worth one specific check. In the current asset system uploads are asynchronous, and an asset entry moves from ASSET_CREATE_PENDING to ASSET_UPLOAD_COMPLETE or to ASSET_ERROR_UPLOAD. Unsuccessful uploads are hidden by default. A filter on upload: { status_not_in: ASSET_UPLOAD_COMPLETE } lists them. Running that query before migrating tells you whether the asset library contains entries with no file behind them.

A pragmatic checklist

  • Read the schema and list models, components, enumerations, remote sources and remote fields separately. The last two are integration scope.
  • Count entries per model, then divide by the page size the project’s age allows. That number is the export runtime.
  • Write the export as a cursor loop on pageInfo, resumable, one model at a time.
  • Establish which asset system the project uses, and grep content for media.graphassets.com before importing.
  • List every localisable field and decide the Payload localisation strategy before exporting.
  • Query for assets whose upload never completed.
  • Import entries with source identifiers retained, then resolve references in a second pass.
  • Decide where composition happens after Hygraph, and price it as its own piece of work.

How WAYF can help

WAYF is an official Payload partner and Top Contributor. We build Payload and Next.js platforms, and we run CMS migrations where the content model, the assets, the locales and the integrations all have to land together.

If you are weighing a move off Hygraph, book a call and we will scope the export, the federation replacement, and the cutover path against your actual schema.

FAQ

  1. Does Hygraph have a content export?

    There is no single export command that hands you the project as a file. Content comes back through the GraphQL Content API, which generates a singular and a plural query for every model plus connection queries for cursor paging. Hygraph documents five pagination arguments, first, last, skip, before and after, and it follows the Relay cursor connection specification with pageInfo fields including hasNextPage and endCursor. The page size is the constraint: for projects created after 14 June 2022 the default result size is 10 and the documented maximum for first or last is 100, while projects older than that default to 100 with a maximum of 1000. An export is therefore a paging script per model.

  2. How do Hygraph components map onto Payload?

    Models become collections and components become embedded structures inside them. Hygraph documents the distinction plainly: models create standalone entries that can be queried on their own, while components reuse a field structure and each instance stores its own content inside the entry. That maps onto Payload groups, arrays and blocks, and leaves collections for the models. Basic components hold one component type in a field and modular components allow two or more. Payload's blocks field is built for that second shape. One detail worth checking before you plan the transform: the Hygraph Studio interface shows up to 50 component instances per entry, and instances past that remain queryable through the API while staying invisible in the UI.

  3. What happens to federated content when you leave Hygraph?

    It stays where it always was. Hygraph documents content federation as a way to integrate content from multiple systems into the Hygraph API without migrating the content itself, and a remote source as a custom resolver entry point that sources data from an external third-party web service at query time. Nothing federated is stored in Hygraph, so nothing federated appears in an export. What a migration has to replace is the composition layer: the single GraphQL endpoint that stitched those systems together. The systems of record are untouched and still need connecting to whatever renders the site afterwards.

  4. Which Hygraph asset system does the project use, and why does it matter?

    Projects created after February 2024 use Hygraph Asset Management and older projects used the Legacy asset system. The two serve assets from different URLs: the legacy form is media.graphassets.com followed by transformations and a handle, and the current form is a regional subdomain of graphassets.com followed by an environment identifier, transformations, the handle and an optional filename. Hygraph sunset the old asset domain after the end of June 2025. It matters for a migration because the asset-system move rewrote asset URLs inside Markdown and Rich Text fields but not inside Single Line, Multiple Line or JSON fields, so a project that stored asset URLs in those field types may still hold addresses that no longer resolve.

  5. Do localised fields move as whole entries?

    No. Localisation in Hygraph is configured per field, so an entry can hold a localised title beside a field that returns the same value in every locale. Reading everything back means querying the localizations field, which returns the locales that have values and takes includeCurrent: true to include the default locale alongside them. Hygraph also accepts a locale list through the gcms-locales header and returns locales in the order requested, from left to right, as a fallback chain. An export that queries one locale at a time will silently flatten that structure, so the transform should carry the per-field shape into whatever localisation strategy the Payload build uses.

Sources


Author

Paul Utr

Co-founder, Chief Growth Officer

Paul has been launching online platforms since his teens, picking up UX and product design by building them. He led the Mailgun redesign at Netguru and was Principal Designer at Ramp Network through its seed-to-Series-B run. At WAYF he leads design and organisational alignment, and watches how language carries through every product we ship.


Rather have it done for you? WAYF runs Hygraph to Payload migrations end to end.

We're booking content platform
engagements for 2026.

Twenty-five minutes to walk through the work and decide if we're the right team for it. Scoping and a fixed price come after.