Migrate from Contentful to Strapi

A planning guide for moving a Contentful space to self-hosted Strapi: what the export carries, what you rebuild by hand, and how to cut over safely.

On this page

Migrate from Contentful to Strapi: what the move involves

If you are facing a Contentful renewal, a data residency requirement or lock-in concerns, understand early that moving to Strapi is a schema rebuild plus a content transform, not a file copy. Contentful content types have to be recreated as Strapi content types, entries have to be reshaped to fit them, and rich text, references and assets have to be rewritten for the new target. Platform or content engineering teams usually own this work, often with an implementation partner who has done similar moves, and the effort depends mostly on how many content types, locales and custom integrations the space contains. The Contentful CLI space export is the starting point. It captures the published content model, entries, assets, locales, webhooks and editor interfaces as JSON, and can download asset files. It does not export roles or permissions, so your access model must be designed again in Strapi from scratch. Run the export against a space you have confirmed is complete, and inventory memberships, webhook credentials and any UI extensions separately, since those are outside the export's scope. Confirm the exact export options with the current Contentful CLI documentation before you script the run. On the hosting side, plan for Strapi 5's requirements before choosing servers. Strapi 5 supports PostgreSQL 14 or later, MySQL 8.0 or later, MariaDB 10.3 or later and SQLite 3, and it does not support MongoDB or other NoSQL databases. It also runs only on Active or Maintenance LTS Node.js versions, so confirm the current LTS line against the Strapi installation requirements when you size the build environment. Choosing a supported database early avoids reworking the import scripts later.

Which Contentful features map cleanly to Strapi

This table maps each Contentful feature in a space export to its closest Strapi equivalent and marks it as clean, needs rework or gap. Read the rows top to bottom as a migration checklist, and treat roles, admin SSO and audit logs as items to plan and price before cutover.

Contentful featureStrapi equivalentMigration status
Content typesCollection types and single types, defined in Strapi's content-type builder or codeNeeds rework: field types, validations and references must be re-declared by hand or by script
EntriesEntries stored as documents through the Document Service APIClean for flat fields, needs rework for linked and nested entries
Assets and filesMedia Library assets, re-uploaded from the downloaded asset filesNeeds rework: the export lists asset metadata, so files must be downloaded and re-uploaded
LocalesInternationalization (i18n) locales per field and entryNeeds rework: map locale codes and fallback chains before importing entries
Rich textStrapi rich text or blocks field, not Contentful's document JSONNeeds rework: embedded entries and links must be transformed
WebhooksStrapi webhooks configured in the admin panelNeeds rework: endpoints and payload shapes are not carried over, so rebuild and test each one
Editor interfacesAdmin panel field layout and list viewsGap: Contentful editor UI extensions and custom widgets have no direct equivalent
Roles and permissionsUsers and Permissions plugin and admin roles, configured by handGap: roles and permissions are not in the space export, so rebuild every role from scratch
Admin SSO and audit logsAdmin SSO and audit logs are Enterprise Edition or paid tier featuresGap on Community: confirm the plan and license terms before cutover
Content APIREST and GraphQL APIs with the v4 response format header available during transitionNeeds rework: client queries and SDK calls must be updated to the new response shape

What the export carries and what you rebuild

The Contentful CLI space export gives you the content side of the move as JSON and downloadable asset files. Access, integrations and the runtime pieces around the content do not travel, so they become a separate rebuild list for the Strapi project. Check each item against the export flags in the CLI docs before you run it.

Content model and entries

The export writes content types, entries and their field definitions as JSON, which is the input for your Strapi content types and imported entries. Map each Contentful content type to a Strapi collection type or single type, then decide how fields such as references, components and localized values translate. Confirm in the CLI docs which export flags return the draft or published state you need, because the export is documented as covering published content.

Assets and asset files

Asset metadata comes out as JSON, and the CLI can also download the asset files themselves. Plan a re-upload step into Strapi's media library so that entries point to the new asset IDs, not the Contentful URLs. Verify that every file downloaded and that embargoed or restricted assets were handled, since access rules on the Contentful side do not carry over.

Locales and editor interfaces

Locales are included in the export, so you can recreate locale settings in Strapi's internationalization configuration before importing localized entries. Editor interfaces are also exported as JSON, but they describe Contentful's own editing layout and do not map to Strapi's admin panel. Treat them as a reference for field ordering and help text, not as configuration to import.

Roles, memberships and permissions

Roles and permissions are not part of the space export, so every Contentful role must be rebuilt as a Strapi role with explicit content type permissions. Memberships are also absent, which means the list of people who need admin access must come from your identity team, not from the export. Decide early whether admin login goes through single sign-on, since that is configured separately from end-user access.

Webhooks and their credentials

Webhook definitions are exported, but the credentials and secrets attached to them are not, so each endpoint needs fresh tokens or signing secrets on the Strapi side. Rebuild the webhook targets for your build or deploy pipeline, and test each one against a staging frontend before cutover. Stale webhooks that still fire at Contentful endpoints are a common source of confusion after a switch.

Frontend integrations and preview

Contentful's delivery and preview API keys, SDK calls and preview configuration live in your frontend code and hosting platform, and none of them are exported. Your front end will need new API endpoints, tokens and a preview route pointing at Strapi, with Strapi's response format and Document Service changes accounted for. Inventory every application that reads from the space before you plan the cutover.

How to turn export JSON into Strapi content types and rich text

The transform layer is where most of the migration effort lands, because the export JSON describes Contentful's content model, not Strapi's. Start by mapping each Contentful content type to a Strapi collection type or single type, then map each field to a Strapi field type. Short text, numbers, booleans and dates usually map directly. References and arrays of references need a decision: a Strapi relation for shared entities, or a component for content that belongs to only one parent. Keep this mapping in a versioned file so every field has a named owner and a test. Confirm the field types and options your chosen Strapi version supports before you generate the schema files, because the available set can change between major versions.

Rich text and entry links need the most careful script. A Contentful rich text field is stored as a JSON document tree of nodes, marks and embedded entry or asset references, and Strapi has its own rich text format, so each document must be converted node by node. Decide how embedded entries become components or relations before you write the converter. Resolve every entry link by recording the source entry ID and the new Strapi record ID in a lookup table during import, then write relations in a second pass so every target exists first. Re-upload each asset through the Strapi upload API, then carry over its title, description, alternative text and locale-specific values from the export, and check that asset references in rich text point to the new media records.

Plan a frontend review before cutover, because Strapi 5 changed how content is read and returned. It replaces the Entity Service API with the Document Service API, and the response format differs from the v4 shape that many Contentful-era front ends were written against, so fields and nesting that the code expects may move. During migration, Strapi offers a Strapi-Response-Format: v4 header for backward compatibility, which can help a team stage the frontend change, but confirm how long your Strapi version supports that header in the Strapi v4 to v5 migration guide. Write contract tests against each endpoint your frontend calls, and compare sample responses from both systems for every content type before switching traffic.

The migration sequence from inventory to decommission

This sequence moves a Contentful space into a self-hosted Strapi instance in controlled stages, so each content type is proven before the frontend depends on it. It ends with Contentful retired only after the team has confirmed content parity and kept a retained export for the agreed period.

  1. Inventory content types, locales and integrations

    List every content type, field, locale, environment, webhook, editor interface and integration that reads from the Contentful space, including frontend builds, search indexes and scheduled jobs. Record which consumers call the Content Delivery API and which call the Management API, because each one needs an owner and a cutover plan. Export the space with the Contentful CLI space export command so the inventory matches the JSON you will import. Done when every content type and consumer has a named owner and the export file has been checksummed and stored in a restricted location.

  2. Run a pilot on one content type

    Choose one representative content type with rich text, references and assets, then map it to a Strapi content type by hand. Transform a sample of its entries from the export JSON, including rich text references and asset links, and import them into a throwaway Strapi instance. Have an editor and a developer compare the rendered output against Contentful for the same entries. Done when the pilot entries round-trip without loss and the team has a written list of field mapping rules that the full import will reuse.

  3. Build the Strapi environment on a supported stack

    Provision the production Strapi instance on a database that Strapi 5 supports, which is PostgreSQL 14 or later, MySQL 8.0 or later, MariaDB 10.3 or later or SQLite 3, and run it on an Active or Maintenance LTS Node.js version. Strapi 5 does not support MongoDB or other NoSQL databases, so confirm this before choosing infrastructure. Configure backups, object storage for uploads, roles and the Growth or Enterprise features you have decided to buy. Confirm current Node.js and database versions against the Strapi installation requirements before provisioning. Done when the environment passes a restore test and the admin panel, SSO and roles are configured in a staging copy.

  4. Run the full import and reconcile counts

    Import all content types, entries, locales and assets using the mapping rules from the pilot, then re-upload asset files into your storage and rewrite asset references to the new URLs. Rebuild roles and permissions by hand, since the Contentful export does not carry them, and recreate each webhook as a Strapi lifecycle or webhook configuration. Reconcile entry counts, locale coverage, publish states and asset checksums between the two systems and log every mismatch. Done when reconciliation reports zero unexplained differences and each rebuilt webhook has fired successfully in a test environment.

  5. Switch frontend reads in stages during a parallel run

    Keep Contentful as the system of record while Strapi serves a growing share of frontend reads, starting with low-risk routes and then moving the rest. Editors work in both systems during this period, so define which system takes writes and how any divergence is resolved. Monitor API response shapes, rendering errors and publish latency on each route before moving the next one. Done when every frontend route reads from Strapi, editors have confirmed their workflow in the new admin panel, and open divergence issues are closed.

  6. Cut over inside a freeze window

    Announce a content freeze in Contentful, run a final delta export and import, reconcile the delta, then point all remaining consumers and webhooks to Strapi. Switch the Contentful API tokens to read-only or revoke them only after the last consumer has confirmed the new endpoints. Keep a rollback path documented, bearing in mind that Strapi does not support downgrades once data has been migrated. Done when the final reconciliation is clean, all consumers report healthy traffic against Strapi, and the freeze has been lifted.

  7. Decommission Contentful after the retention period

    Once the agreed retention period has passed, keep a final verified export and the migration records in your own archive, then remove integrations, revoke remaining tokens and end the Contentful subscription at the renewal date. Confirm with Contentful how long the space and its assets remain available after cancellation and what the contract requires for data return. Done when the archive has been restore-tested, the subscription end date is confirmed in writing, and the decommission record is signed off by the data owner.

How the move differs by space size and starting point

A single-space marketing site with few locales is usually the simplest case. The content model tends to be small, with a handful of page, landing and author types, and the number of entries is often modest enough to review by hand after import. The main decisions are whether to rebuild the model in Strapi by hand or script it from the export JSON, and how much of the editorial workflow you need to carry over.

  • Import scope: Most of the export can be mapped directly, so the work centers on content types and components rather than volume.
  • Asset volume: Images and PDFs are often the largest part of the job, so decide early whether to re-upload originals or keep existing CDN URLs for a period.
  • Locales: Confirm each locale and its fallback chain in the export, then create matching locales in Strapi before importing entries.
  • Parallel run: A short overlap with Contentful is often enough, since editors can switch over page by page.
  • Roles: Editor and reviewer roles are few, so rebuilding them by hand is usually quick.

Before committing, ask your implementation partner to confirm the entry count, asset count and locale list from a fresh space export, because these drive the effort more than the content type count does.

What drives the cost and duration of the move

This table lists the factors that change how long the Contentful to Strapi move takes and what it costs, and how to shrink each one. Read the first rows as one-time migration work and the last rows as recurring Strapi costs. The main takeaway is that content model size and rich text complexity usually matter more than raw entry count.

DriverWhy it changes cost or effortHow to keep it down
Number of content types and referencesEach content type becomes a Strapi collection or component with its own schema, and every reference field needs a relation mapped and tested. Dense reference graphs multiply validation work.Audit the export's content model first, remove unused types, and migrate referenced types before the entries that point to them.
Rich text complexityContentful rich text is a JSON document with embedded entries and assets. Strapi needs a converted format, so custom node types or embedded components require transformation code and manual review of rendered output.Inventory which node types and embedded entries are in use, and limit the set of rich text features your editors actually rely on.
Asset volume and download timeThe CLI can download asset files, but the total time depends on file count, file size, and any embargoed assets that need access. Re-uploading to Strapi's media library adds a second pass.Export assets in batches, separate published from archived files, and confirm storage capacity on your own infrastructure before the run.
Number of localesEach locale multiplies entries and field values. Strapi's i18n handling must be enabled and each localized field checked for fallback behavior.Confirm which locales are live and drop retired ones from the export scope before mapping.
Webhook count and downstream consumersContentful webhooks are not carried over as live integrations, so each one must be rebuilt in Strapi and its receiving systems re-pointed. Every consumer adds testing.List each webhook with its receiver and owner, and retire any that feed systems you are also replacing.
Frontend couplingIf the frontend reads Contentful's delivery API directly, changing response shapes forces frontend work. Strapi 5 also has its own response format, so queries need rewriting.Put a data access layer between the frontend and the CMS so the query rewrite happens in one place.
Roles and permissions to rebuildThe export does not include roles or permissions, so every role, space membership and editor scope is recreated by hand in Strapi's admin panel and Users and Permissions settings.Document current roles from Contentful before exporting and reduce them to a short set of named permission groups.
One-time migration workSchema mapping, scripted import, rich text transformation, asset re-upload and QA are paid as project effort, usually through an implementation partner or your own team. These costs do not recur once cut over.Ask a partner for a fixed-scope written quote that lists each step, the content types in scope, and what testing is included.
Recurring Strapi costs by planSelf-hosted Strapi's Community plan is free with unlimited users. The Growth plan is listed at 45 US dollars per month including 3 users, plus 15 dollars per extra user, according to Strapi's self-hosted pricing page. Enterprise is custom priced.Confirm which features you need, such as SSO, audit logs or review workflows, since those drive the plan choice. Request a written quote for Enterprise before assuming it is needed.
Infrastructure and operationsHosting, database, media storage, CDN, upgrades and backups recur for as long as you run Strapi. Strapi 5 supports PostgreSQL 14 or later, MySQL 8.0 or later, MariaDB 10.3 or later and SQLite 3 per its installation docs.Choose a supported database version, size storage from the asset inventory, and budget for upgrades on Strapi's frequent minor releases.

Running Contentful and Strapi in parallel before cutover

Keep Contentful as the single editing source until Strapi has proven it can serve the same content correctly. During dual-running, editors keep working in Contentful, a scripted sync job writes each published entry and asset into Strapi, and the frontend stays on Contentful reads. The sync script should map entries through the same field transformations used in the initial import, so drift is limited to content that changed after the last run. Before the first sync, agree on the Strapi content types as code, since changing a schema midway through dual-running forces a re-import of every affected entry.

Compare the two APIs before anyone switches reads. Pick a set of sample entries that cover each content type, each locale, nested references, rich text with embedded assets and entries with unpublished drafts, then request them from the Contentful Delivery API and from Strapi's REST endpoints and diff the JSON after normalizing field names and response shape. Strapi 5 uses the Document Service API and a different response format from v4, so expect structural differences in the output and document them in the mapping table rather than treating each one as a defect. Ask the Strapi team or your implementation partner to confirm how your chosen version returns relations, components and dynamic zones before you write the comparison rules.

Take a full database backup of the Strapi environment before any upgrade, schema change or first production import. The Strapi v4 to v5 documentation says to back up the database first because downgrading is not supported, so a failed data migration is recoverable only from that backup. Store the backup outside the application host, test a restore into a separate environment, and record the Strapi version and Node.js version alongside it. Then set the content-freeze decision at cutover: announce a window in which editors stop publishing in Contentful, run a final delta sync, verify the sample entries again, and only then move editor logins and frontend reads to Strapi. Keep Contentful read-only for a defined period so you can recover content if a defect surfaces after cutover.

What usually goes wrong and how to prevent it

Most failed Contentful-to-Strapi migrations break in the gaps between the export and production: access rules, links inside content, media, integrations and licensing assumptions. Each card below names one failure, why it matters for this move, and the check that catches it before editors and users do.

Roles do not come across

The Contentful CLI space export carries the content model, content, assets, locales, webhooks and editor interfaces, but not roles or permissions. Every editor, reviewer and API consumer needs an explicit role in Strapi, and those roles must be designed from scratch. Before cutover, list each Contentful role and environment permission, map it to a Strapi role with content-type level permissions, and have editors test create, edit and publish on a staging copy.

Rich text and entry links break

Contentful rich text stores embedded entries and inline links as structured nodes that point to entry and asset IDs. Strapi uses its own content types, relations and block formats, so a naive import leaves dangling references or flattens them to plain text. Write a transform that converts each entry-hyperlink and embedded-entry node into a Strapi relation or component, then run a script that reports every ID it could not resolve.

Asset URLs stop resolving

Contentful serves assets from its own CDN, and some assets can be embargoed. If the export keeps the original URLs in content, pages will break the day the Contentful space is closed. Download the asset files during export, upload them to your storage provider, and rewrite stored URLs to Strapi's upload records. Check that every asset reference resolves in the new environment and that embargoed files were fetched while access still existed.

Webhooks fire into the wrong place

Contentful webhooks are exported as configuration, but the destination URLs and any credentials are tied to the old stack. Left as-is, a publish can rebuild the old frontend, call a retired endpoint or fire nothing at all. Inventory every webhook, recreate the triggers as Strapi webhooks, and test each one against a non-production frontend. Confirm which consumers still need the event and remove the rest.

SSO assumed to cover end users

Strapi SSO applies only to administrator login to the admin panel through an identity provider such as Microsoft Azure Active Directory, including auto-registration and a default role. End-user authentication on the website or app is handled separately by the Users and Permissions plugin. Teams that wire SSO and assume their customers or members are covered will ship a gap. Decide who signs in where, configure the admin SSO, and test public user login as its own item.

Enterprise features assumed included

On the self-hosted plans, audit logs and review workflows are Enterprise features, SSO is an add-on for Growth and included in Enterprise, and content history and releases start at the Growth plan. Code under the ee directories falls under the Enterprise license unless you hold a signed agreement or a Strapi Cloud subscription. Before committing to a design that relies on approvals or audit trails, check the plan and license terms in writing with Strapi and ask your compliance team which controls depend on them.

Questions buyers ask before moving from Contentful to Strapi

What drives the total cost of moving from Contentful to self-hosted Strapi?

The cost is mostly labor plus the infrastructure you then run, and the split between one-time and recurring costs matters more than any single line. One-time work covers mapping content types to Strapi schemas, transforming rich text and references, re-uploading assets, rebuilding webhooks and roles, and testing the frontend. Recurring costs cover hosting, the PostgreSQL or MySQL database, asset storage, a CDN, backups, Node.js upgrades and Strapi version upgrades. Community Edition has no license fee, so the Growth or Enterprise plans only apply if you need the features they include. For the self-hosted plan prices, the Strapi self-hosted pricing page lists Growth at 45 US dollars per month including 3 users. Ask any implementation partner for a quote that separates one-time migration effort from recurring hosting and support, and compare it with your current Contentful subscription and usage charges.

How long does a Contentful to Strapi migration take?

The timeline depends mainly on how many content types, locales, references and assets you have, and how much frontend code reads from Contentful's API. Schema design and rich text transformation usually take longer than the data import itself, because each content type needs a matching Strapi content type and each rich text field needs a deliberate mapping. Asset volume and download speed also set how long the file transfer runs. Webhook rebuilds and editorial sign-off add further steps. No duration figure is supplied here, so ask for a fixed-scope plan with milestones before committing. A written scope lets you compare options on the same basis.

What does the migration need from our own team?

Your team supplies the content model knowledge, access and decisions that no export file can record. You need someone who owns the current Contentful space, can export it with the Contentful CLI, and can confirm which content types, locales and environments are live. Frontend engineers must identify every query and API response shape the site uses, because Strapi 5 changes the API response format. Editors must review sample content after transformation, and security staff must define the roles and identity provider setup. The Contentful CLI export does not include roles and permissions, so your team must recreate those rules in Strapi from documented requirements.

Can an in-house team migrate from Contentful to Strapi without outside help?

A capable in-house team can do it, provided it has engineers who know Node.js, Strapi content modeling and the target database, and it can give the work enough time. The harder parts are rich text and reference transformation, asset re-uploads, and rebuilding roles and webhooks without breaking the live site. Teams with little prior Strapi experience often underestimate the upgrade and deployment work. An external partner can take the scope as a fixed deliverable, document it and hand over the running system. Decide on the split based on skills, deadlines and who will support Strapi after launch. DeployOpen plans, implements and documents self-hosted platforms in your own infrastructure under a written scope.

Which Strapi features require the Enterprise Edition license?

Strapi is open core, so the Community Edition under the MIT license covers core content management, while code in ee directories falls under the Enterprise Edition license. According to Strapi's self-hosted pricing page, audit logs and review workflows are Enterprise features, and SSO is an add-on for Growth and included in Enterprise. Content history and releases start at the Growth plan. Enterprise pricing is custom, so request a written quote. Confirm with Strapi which features your use case needs before you design around them, because the license file governs use of the ee code.

Can Strapi 5 run on our existing database?

Strapi 5 runs on PostgreSQL 14 or later, MySQL 8.0 or later, MariaDB 10.3 or later and SQLite 3, but it does not support MongoDB or other NoSQL databases. If your existing database is one of the supported engines and at a supported version, Strapi 5 can use it, but you should still confirm the version and the Node.js version you plan to run. Strapi runs only on Active or Maintenance LTS Node.js versions. Because Strapi 5 uses a new data model and Document Service API, the export data must be imported into a new Strapi schema rather than simply pointed at an old database. Back up the database first, since the Strapi migration docs state that downgrading is not supported.

What are the main operational risks after moving to self-hosted Strapi?

After the move, your team owns uptime, backups, security patches, Node.js updates and Strapi upgrades that Contentful previously handled as a hosted service. Strapi 5 minor releases ship frequently, so plan a regular upgrade cadence and test it in staging. Protect the admin panel with SSO where your policy requires it, and note that Strapi SSO covers administrator login only, while end-user authentication uses the Users and Permissions plugin. Set up monitoring, tested restore procedures and access reviews. Ask your partner to document the runbook, backup schedule and upgrade procedure as part of the handover.

How does Strapi self-hosting compare with Strapi Cloud for cost?

Self-hosting moves hosting, storage, bandwidth and operations cost onto your own infrastructure, while Strapi Cloud bundles them into a plan. Strapi Cloud is listed at 35 US dollars per month per project for Starter, 90 for Pro and 450 for Business, according to the Strapi Cloud pricing page, with allowances for API requests, storage and bandwidth. The Business plan includes a 99.9% uptime SLA. Self-hosting gives you control of data location and infrastructure but no vendor SLA, so you must fund the staff time to meet your own availability targets. Compare both options using the same traffic, storage and staffing assumptions.

How DeployOpen scopes and runs a Contentful to Strapi move

DeployOpen plans, implements, integrates, hardens, backs up and documents self-hosted Strapi inside your own cloud account, data center or air-gapped network, so the CMS, its database and its media storage sit where your security team already has controls. Work starts from a fixed-scope written agreement that names the deliverables, the content types to be rebuilt, the locales and asset volumes in scope, the webhook consumers to be re-pointed and the environments to be handed over. Before a quote is issued, the scope should state which Contentful space exports are in scope, whether the Strapi version is pinned to the current 5.x line, and who owns the frontend cutover. DeployOpen does not publish a price list. A quote follows from that written scope, so the more precisely the content model, integrations and Strapi edition needs are described up front, the more closely the quote tracks the work.

Delivery typically covers the parts of this migration that take the most judgment: building Strapi content types from the exported Contentful model, configuring roles and permissions that the export does not carry, rebuilding webhooks, setting up PostgreSQL or another supported database with tested backups, and writing the runbooks your operations team will use after handover. Where you need evidence for an internal or external assessment, DeployOpen can run security testing against the Strapi admin panel, the content API and the hosting layer, and can prepare documented controls and records. DeployOpen prepares that evidence but does not issue audit reports, attestations or certifications; your independent auditor or certification body does that work.

Ongoing needs are handled through separate retainers for upgrades, patching, monitoring support and continuous testing, which matter because Strapi ships frequent minor releases and the v4 line has reached end of life. Ask any implementation partner, DeployOpen included, to show how its scope separates one-time migration work from recurring operations, and to state in writing who carries the Strapi Enterprise Edition license decision, since that choice affects SSO, audit logs and review workflows. Confirm each of these points against your own environment and your procurement policy before signing.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.