macrostack
Migration guide · Layer 5

Contentful → Strapi

What it saves, what actually moves, what you rebuild — and the thing that catches people.

What it costs, and what it saves

Contentful, as listed on its pricing page on 2026-10-03: Free is $0 with hard caps (10 users, 2 roles, 2 locales, 100K API calls and 50 GB CDN bandwidth a month, one Starter Space of 25 content types, 2 environments and 10,000 records). Lite is $300/month (20 users, 3 roles, 3 locales, 1M API calls, 100 GB bandwidth); a larger Lite Space (50 content types, 4 environments, 50,000 records) is $850/month on top, and overage is $5 per extra 1M API calls and $0.15 per extra GB. Enterprise is quoted. Strapi, as listed the same day: the self-hosted Community edition is $0 under the MIT licence with no caps on entries or API calls; self-hosted Growth is $45/month including 3 seats (+$15 per seat) and adds Live Preview, Releases and 14-day Content History; Enterprise is quoted. Strapi Cloud is $35/month per project (Starter: 100k API requests, 50 GB storage and bandwidth), $90 (Pro) or $450 (Business). Self-hosting moves the cost to your own server and database (PostgreSQL 14+, MySQL 8.0+, MariaDB 10.3+ or SQLite) and the time spent patching and backing them up. That cost is not priced here.

86
Strapi
MIT core, with enterprise features under a separate commercial licence
Effort: Estimate, not a measured figure: about 1 to 3 weeks of developer time for one space with 10 to 25 content types and one or two locales. Expect longer with heavy Rich Text, many locales or many references that accept several content types.

Moves cleanly

Entries and their plain field values (short and long text, numbers, booleans, dates, JSON objects) and the asset files themselves move with a script. `contentful space export` writes one JSON file with content types, entries, assets, locales, tags, webhooks, roles and editor interfaces, and `--download-assets` saves the binary files so they can be uploaded to Strapi's media library. A Reference field that points at a single content type maps directly to a Strapi Relation field.

You rebuild

You recreate the content model by hand in Strapi's Content-type Builder, which runs only in development mode, because `strapi import` reads nothing but archives made by `strapi export`. You also rebuild or convert, rather than import: Rich Text, references that accept several content types, field-level locales, roles, webhooks (Contentful exports them without credentials), space memberships and custom UI extensions.

What Contentful costs you today

The free tier covers a small project. Lite is around $300/month, and Premium is quoted and commonly reaches five figures a year. Three separate meters run at once: users, content records, and API calls — so a site that gets popular can raise its CMS bill without anyone adding a single article. Figures checked 2026-08-05.

What actually holds you in

Moderate, and concentrated in the model rather than the text. Entries export as JSON through the CMA API, so the words come out. What does not come out cleanly is the content model — field types, validations, references between types and localisation settings — which has to be rebuilt in the new system, and every front-end query written against Contentful's API shape needs rewriting. Teams with a simple blog migrate in days. Teams with deeply referenced multi-locale models are migrating a schema.

What you are moving to

Strapi is the most widely deployed open-source headless CMS: a content-type builder, REST and GraphQL APIs, role-based permissions, internationalisation and a large plugin marketplace. Around 73k stars. It is the safe choice in the sense that most problems you hit have already been asked about somewhere. Licensing is mixed and worth checking against your needs: the core is MIT, but a number of enterprise features — SSO, audit logs, advanced permissions — sit under a separate commercial licence.

Community edition free and self-hostable. Enterprise and Cloud tiers are paid.

Strapi strengths

  • Largest community and plugin ecosystem of any open headless CMS
  • Content-type builder that non-developers can use
  • REST and GraphQL out of the box
  • Mature, with years of production deployments

What you give up

  • SSO, audit logs and advanced permissions are commercial
  • Major version upgrades have been disruptive historically
  • Heavier to run than Payload
  • Single-vendor governance

The migration, step by step

  1. 1Run `contentful space export` with `--include-drafts`, `--include-archived` and `--download-assets`. By default drafts are skipped and assets are only links to Contentful's CDN, so without these flags you get neither the drafts nor the image files.
  2. 2Recreate each content type in Strapi's Content-type Builder on a local development instance. Add a `contentful_id` field to every type so the import script can be re-run without creating duplicates and can resolve links later.
  3. 3Write an import script against Strapi's Document Service API (`create()` with `locale` and `status: 'published'`). Upload assets first, then entries, then make a second pass that fills in relations once every target entry exists.
  4. 4Convert Rich Text from Contentful's JSON node tree to Strapi's Rich text (Blocks) or Markdown field. Point embedded image URLs at the new media library files, and turn embedded entries into relations or components.
  5. 5Run both CMSs side by side. Point a staging build of your front end at Strapi's REST or GraphQL API, compare the rendered pages with production, then freeze editing in Contentful before the final export.
  6. 6Cut over: re-run the script for entries changed since the first export, then switch the front end's API URL and your webhooks to Strapi. Keep the Contentful space read-only until you have checked image URLs and search traffic on the new build.

The gotcha

Two differences in how the two products model content only show up once the import script runs. First, a Contentful Reference field can accept several content types: the content-type API's `linkContentType` validation takes an array such as ['post','doc','product']. Strapi's documentation says a Relation field must target a collection type, and it points at exactly one. Each mixed-type reference therefore becomes a dynamic zone of components or several separate relation fields, and the front-end queries that read it change too. Second, Contentful localises field by field, with custom fallback chains. Strapi i18n stores each locale as its own version of a document, and content 'can only be managed one locale at a time'. Fields that were not localised in Contentful have to be copied into every Strapi locale, and fallback logic moves into your front end. Strapi's own `strapi import` cannot help with any of this: it accepts only Strapi export archives, requires identical schemas, and deletes all existing data and uploads before it restores.

When to stay on Contentful

Stay if your editors rely on Contentful's field-level localisation with custom fallback chains, on scheduled publishing, comments and live collaboration (Lite), or on Enterprise features such as embargoed assets, locale-based publishing and connected Spaces. Also stay if nobody on the team wants to run, patch and back up a Node.js server and its database. A project that fits the Free plan's caps (10,000 records, 2 locales) already costs nothing on Contentful.

Compare firstAll 5 Contentful alternatives, rankedWhere this sitsLayer 5 — Applications

More Layer 5 migrations

Figures verified 2026-08-05 against vendor pricing pages. Prices change and migrations differ by estate — treat the cost delta as a starting model, not a quote. Rankings and recommendations here are merit-only; affiliate income never changes a verdict. See our methodology.

The Macrostack brief

New swaps, worth your inbox.

A short, occasional email when we add a high-intent alternative or ship a new head-to-head. No spam, no selling your address — unsubscribe in one click.