own contentful content on your postgres
move the model into version control, keep familiar delivery APIs, and stop tying the bill to request volume. Apache-2.0 core, self-host free forever.
pepper migrate --from contentful
reading content types from contentful
mapping fields to chili.config.ts
writing postgres migrations + RLS policies
generated an import plan for review
done. your content is ready for Postgres.
- SQLquery your content directly
- $0self-host, free forever
- Apache-2.0open-source core
- 0per-API-call charges
chilicms vs contentful, line by line
contentful is a mature, hosted, closed-source SaaS priced on seats and API operations. chilicms is open-source and runs on your Postgres. the rows below mark where each side wins — including the ones we lose.
| capability | ChiliCMS | Contentful |
|---|---|---|
| where it runsyour infra vs their cloud | your Postgres | hosted SaaS only |
| self-host the coreApache-2.0, no feature paywall on launch features | ||
| open-source licenseContentful is closed-source, proprietary | ||
| pricing modelwe charge for workspace shape, never per API call | workspace shape | seats + API ops |
| list price, mid tierContentful's published Team plan vs our Team plan | $199/mo | $300/mo |
| data ownershippoint psql at real tables vs export through their API | direct Postgres | API export |
| GraphQL + REST from one schema | ||
| schema-as-code in version controlchili.config.ts is canonical; their schema lives in their UI/API | ||
| row-level multi-tenancyFORCE ROW LEVEL SECURITY in Postgres vs space-scoped roles | ||
| one-command migration inpepper migrate --from contentful | ||
| app marketplaceContentful has ~100 marketplace apps; we have a handful | ||
| global CDN delivery networktheir content CDN is years ahead; ours is your CDN + cache | ||
| enterprise track recordContentful runs at Fortune-500 scale; we are younger | ||
| SOC 2 / ISO certifications todaywe are mid-audit; Contentful holds the full set now | ||
| managed uptime SLA out of the boxhosted means they own the pager; self-host means you do |
where contentful still wins
contentful has a decade of head start. its app marketplace runs past a hundred integrations, its global delivery CDN is genuinely ahead of anything you assemble yourself on day one, and it carries the SOC 2 and ISO certifications a procurement team asks for.
it is also fully managed. when delivery breaks at 2am, their pager fires, not yours. self-hosting moves that responsibility to your team. for a regulated org with no platform engineers to spare, that trade can land in contentful's favor.
we are younger, mid-audit on certifications, and still growing the ecosystem. if those gaps block you today, we would rather you knew now than found out after a migration.
moving off contentful is one command
point pepper at your space, review the generated schema in a pull request, then read your content back over the same GraphQL and REST you already use.
migrate, then read
# point pepper at your Contentful space + token
pepper migrate --from contentful \
--space $CONTENTFUL_SPACE_ID \
--token $CONTENTFUL_CMA_TOKEN
# → maps content types to chili.config.ts (schema-as-code)
# → writes migrations + RLS policies
# → copies entries and assets into your Postgres# same query shape you already know from Contentful
query Posts {
posts(status: PUBLISHED) {
id
title
publishedAt
}
}import { createClient } from "@chilicms/sdk"
const chili = createClient({ baseUrl: "https://api.chilicms.dev" })
const posts = await chili.list<{ title: string }>("posts")questions from contentful teams
Why leave Contentful?
Two reasons we hear most: the bill scaling with API operations instead of with your content, and the data living in someone else's cloud. ChiliCMS charges for workspace shape, not per call, and the content sits in your own Postgres where psql can read it.
Does the GraphQL API match what I have today?
Partly. REST serves custom content types today, and GraphQL covers the built-in session surface. Field names and query shapes carry over for many models, but Contentful-specific niceties like their Rich Text JSON format need a mapping step, which pepper migrate handles for the common cases.
How does the migration actually work?
pepper migrate --from contentful reads your space through the Content Management API, maps each content type to chili.config.ts, writes the Postgres migrations and row-level-security policies, then copies entries and assets across. You review the generated schema in a pull request before anything goes live.
What does Contentful still do better?
Plenty, and we will not pretend otherwise. Contentful has a deeper app marketplace, a more mature global delivery CDN, a longer enterprise track record, and the full set of SOC 2 and ISO certifications today. If a hosted SLA and a large app ecosystem outweigh data ownership for you, Contentful is the safer call right now.
Is ChiliCMS free if I self-host?
Yes. The core is Apache-2.0 and self-host is free forever, with no feature paywall on anything that shipped open at launch. You run one container plus your Postgres. Enterprise add-ons live under a separate BSL license that auto-converts to open source after four years.
own your content, not a contentful invoice
Migrate with one command, run it on your Postgres, and pay for workspace shape instead of API calls. Apache-2.0, self-host free forever.