Kentico to Contentful Migration: A Technical Guide
How to migrate content from Kentico Xperience 13 to Contentful: SQL extraction, HTML-to-Rich-Text conversion, CMA rate limits, content model mapping, and validation.
Planning a migration?
Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.
Schedule a free call- 1,500+ migrations completed
- Zero downtime guaranteed
- Transparent, fixed pricing
- Project success responsibility
- Post-migration support included
Kentico to Contentful Migration: A Technical Guide
TL;DR: Kentico to Contentful migration requires flattening a hierarchical SQL-backed page tree into flat, API-delivered entries and converting raw HTML into Contentful's strict JSON Rich Text AST. There is no connector — you need a custom ETL pipeline, and the Rich Text conversion is the hardest part.
Migrating from Kentico (Xperience 13 or earlier) to Contentful means moving from a monolithic .NET CMS with a relational SQL Server database, page-tree hierarchy, and coupled data tables — to a headless, API-first platform where everything is a typed entry in a JSON content model and rich text is a structured AST, not HTML.
There is no off-the-shelf migration connector between these two platforms. You need a custom ETL pipeline: extract from Kentico's SQL database or REST API, transform page content and HTML into Contentful's Rich Text JSON document format, and load entries through the Content Management API (CMA) while respecting rate limits and dependency ordering. The hardest part is not moving the data — it is reshaping a tree-structured, server-rendered content model into flat, API-delivered structured content.
With Kentico Xperience 13 reaching end of support on December 31, 2026, teams running KX13 have a hard deadline. If your plan is to leave Kentico entirely — not upgrade to Xperience by Kentico — Contentful is a common target, especially for teams that want to decouple content from presentation and adopt a JavaScript or multi-channel frontend.
Important clock distinction: The timelines in this guide describe the data migration itself — extracting, transforming, and loading content from Kentico into Contentful. They do not describe the broader replatform effort (rebuilding frontend templates, integrations, editorial workflows), which is a separate project measured in months. ClonePartner moves the data; we do not rebuild the application.
How Kentico and Contentful Store Content Differently
Before writing extraction queries, you need to understand how fundamentally these two systems differ in their data models.
Kentico uses a relational SQL Server database with a three-table structure for every page. The CMS_Tree table stores tree position and node-level properties shared across language versions. CMS_Document stores culture-specific page properties, widget data, and editable region content — with multiple records per page for multilingual sites. Coupled data tables (e.g., DancingGoat_Article) store the custom fields defined on each page type. URL routing is inherently tied to this physical tree structure.
Contentful stores everything as typed entries and assets inside spaces and environments. Each content type can have up to 50 fields. Rich text is a JSON Abstract Syntax Tree (AST) with a document root node containing typed child nodes — not HTML strings, not Markdown. References between entries use Link objects with sys.id identifiers, not relational foreign keys. There is no inherent hierarchy or page tree.
The mapping table below covers the core concepts:
| Kentico Concept | Contentful Equivalent | Migration Notes |
|---|---|---|
| Page type | Content type | 1:1 mapping, but Contentful limits to 25 types (Starter) or 50 (Lite) per space |
| Page (CMS_Tree + CMS_Document + coupled) | Entry | Flatten the three-table join into a single entry |
| Coupled data fields | Content type fields | Max 50 fields per content type |
| Page attachment | Asset | Upload via CMA, link by sys.id |
| Media library file | Asset | Separate extraction from filesystem or Azure Blob Storage |
| Editable region (HTML) | Rich Text field (JSON AST) | Requires HTML → Rich Text AST conversion |
| Page relationship | Entry link (reference field) | Must resolve to Contentful sys.id |
| Content tree hierarchy | No native tree | Model via parent reference fields or slug conventions |
| Culture versions | Locales | Contentful uses field-level localization |
The architectural mismatch that trips up most teams: Kentico's tree hierarchy has no direct equivalent in Contentful. Contentful entries are flat. If your Kentico site relies on tree position for navigation, breadcrumbs, or URL generation, you need to model that explicitly — for example, with a parent reference field or a slug field that encodes the full path. You must extract Kentico's NodeAliasPath and NodeParentID values and use them to construct reference links between your new Contentful entries during the import phase.
Extraction Method Decision Tree
Choosing the wrong extraction method wastes significant time. Use this decision tree to select your approach before writing any code:
Do you have direct SQL Server access to the Kentico database?
├── YES → Use SQL extraction (preferred for all KX12/KX13 installations)
│ ├── On-premises or self-hosted? → Direct connection string
│ └── Azure SQL? → Connect via Azure portal credentials or managed identity
└── NO
├── Is Kentico cloud-hosted with no DB access granted?
│ ├── Volume < 2,000 pages? → Use REST API with pagination loop
│ └── Volume > 2,000 pages? → Negotiate DB access or request a DB backup
└── Do you only have the Kentico Export Wizard ZIP?
└── Do NOT use for Contentful migration — proprietary format,
no useful mapping to Contentful's data model
How to Extract Content from Kentico
SQL extraction (preferred)
Direct SQL extraction from Kentico's database is the most reliable path for cross-platform migrations. Join CMS_Tree, CMS_Document, and the relevant coupled data table for each page type. The View_CMS_Tree_Joined view simplifies this, but writing explicit joins gives you more control over which columns you extract.
SELECT
t.NodeAliasPath,
t.NodeGUID,
t.NodeParentID,
d.DocumentCulture,
d.DocumentName,
d.DocumentModifiedWhen,
a.ArticleTitle,
a.ArticleSummary,
a.ArticleText,
a.PublishDate
FROM CMS_Tree t
JOIN CMS_Document d ON d.DocumentNodeID = t.NodeID
JOIN DancingGoat_Article a ON a.ArticleID = d.DocumentForeignKeyValue
WHERE t.NodeClassID = (
SELECT ClassID FROM CMS_Class WHERE ClassName = 'DancingGoat.Article'
)
AND d.DocumentCulture = 'en-US'
AND d.DocumentIsArchived = 0
ORDER BY t.NodeAliasPathNote that DocumentModifiedWhen is included here — this field is the basis for delta sync (covered below). Export results as JSON, which maps cleanly to Contentful's ingestion scripts.
Repeat this per page type. Each page type has its own coupled table, so there is no single query that extracts all content — you need one query per type.
REST API (limited use cases)
Kentico Xperience 13 exposes a REST service at <admin-domain>/rest. You can retrieve pages at paths like /rest/content/currentsite/en-us/document/<alias-path>. The REST API returns XML or JSON and supports pagination via ?skip= and ?take= parameters, but maximum page size is constrained to 1,000 records per call. For sites with tens of thousands of pages, looping through all pages at 1,000 records per call introduces significant latency — typically 2–5x slower than equivalent SQL extraction. Use REST only when direct database access is unavailable and content volume is below approximately 2,000 pages.
The Kentico Export Wizard: why it does not apply here
The Kentico export wizard produces a proprietary ZIP format containing XML data packages designed for Kentico-to-Kentico transfers. The format encodes Kentico-internal object references, widget configurations, and tree positions that have no equivalent in Contentful. Parsing this format to produce Contentful-compatible JSON requires more effort than SQL extraction with none of the benefits.
Media and attachments
Kentico stores media in two places: page attachments (binary data in CMS_Attachment or on the filesystem) and media library files (in ~/[SiteName]/media/ or Azure Blob Storage). Both need separate extraction workflows. URLs for media library files typically follow the pattern /getmedia/12345-guid/filename.jpg. For Contentful, every media file becomes an Asset uploaded through the CMA's asset processing pipeline.
Delta sync mechanics
The bulk migration captures a point-in-time snapshot of Kentico content. If editors continue publishing during migration validation, you need a final delta sync before cutover.
Delta sync uses DocumentModifiedWhen as the change-detection field. The process:
- Record the timestamp when the bulk migration extraction began (
T_bulk). - After bulk import and validation complete, query Kentico for all documents where
DocumentModifiedWhen > T_bulk. - Also query for net-new records:
DocumentIDvalues not present in the original extraction result set. - Process only this changed set through the full ETL pipeline.
- For updated records that already exist in Contentful, use the CMA's
PUT /entries/{entryId}endpoint with the currentsys.versionto avoid conflict errors.
For detecting deletions (pages removed in Kentico after the bulk extraction), compare the full set of NodeGUID values from Kentico against the external ID index you built during the bulk import, then unpublish or archive the delta in Contentful.
Content Model Design: What to Decide Before You Import
Do not start importing until your Contentful content model is finalized. Every content type change after import requires re-migration or manual cleanup.
Content type budget
Contentful imposes hard limits on content types per space: 25 content types on a Starter Space, 50 on a Lite Space, with more available on Enterprise plans. A typical Kentico site with 10–15 page types, plus custom module classes and custom tables, can approach the Starter limit fast — especially once you add component-level types for reusable content blocks.
Worked example: consolidating 18 Kentico page types into 12 Contentful content types
A real Kentico site might have these page types that appear distinct but share significant structural overlap:
| Kentico Page Types (Before) | Contentful Content Types (After) | Consolidation Logic |
|---|---|---|
| Article, BlogPost, PressRelease | Article |
Add articleType Symbol field (enum: article/blog/press-release); all three share title, body, author, publishDate, tags |
| ProductPage, ProductVariant | Product + ProductVariant |
Keep separate — variant references parent product via Link field |
| TeamMember, Author | Person |
Both have name, bio, image, role; merge with personType field |
| LandingPage, CampaignPage | LandingPage |
Both are single-use, non-hierarchical; distinguish via campaignTag |
| FAQ, FAQCategory | FAQ + FAQCategory |
Retain hierarchy via reference field |
| NewsItem | merged into Article |
Identical field structure |
| OfficeLocation, StoreLocator | Location |
Merge geographic content types; add locationType field |
| EventPage | Event |
Retain — unique fields (startDate, endDate, venue, registrationUrl) |
| DocumentPage | Merge into Resource |
PDF/download pages with no body content |
| ResourceHub, DownloadCenter | Resource |
Both are asset-delivery wrappers |
Result: 18 Kentico page types → 12 Contentful content types. The consolidation preserves all semantic distinctions through taxonomy fields while staying within Starter plan limits.
Field mapping rules
- Short text fields →
Symbol(max 256 characters) - Long text / HTML body →
RichText(JSON AST) orText(Markdown/plain) - Date fields →
Date(ISO 8601) - Boolean fields →
Boolean - Image/file fields →
Linkto Asset - Related pages →
ArrayofLinkto Entry - Categories/tags → Contentful tags (up to 100 per entry) or a dedicated taxonomy content type with references
Each Contentful content type supports a maximum of 50 fields. If a Kentico page type has more than 50 coupled data columns (rare but possible in legacy installations), you will need to split it into multiple linked content types or drop unused fields.
How to Convert Kentico HTML to Contentful Rich Text
This is the hardest transformation in a Kentico to Contentful migration. Contentful Rich Text is a JSON AST — a tree of typed nodes (paragraph, heading-1, embedded-entry-block, etc.) with content arrays and data objects. Kentico stores body content as raw HTML strings, often littered with inline macros (e.g., {% CurrentDocument.DocumentName %}), shortcodes, and hardcoded relative links to internal pages or media files.
You cannot paste HTML into a Rich Text field via the CMA. You must convert it to the Rich Text document structure. A simple paragraph in Contentful looks like this:
{
"nodeType": "document",
"data": {},
"content": [
{
"nodeType": "paragraph",
"content": [
{
"nodeType": "text",
"value": "This is extracted from Kentico.",
"marks": [],
"data": {}
}
],
"data": {}
}
]
}Failing to strictly adhere to Contentful's Rich Text schema results in validation errors from the CMA, causing the entire entry creation to fail.
Tooling comparison
| Tool | Type | Supported Input | Key Limitations | Maintenance Status |
|---|---|---|---|---|
@contentful/rich-text-from-markdown |
Official npm package | Markdown | No HTML support; requires pre-conversion of HTML to Markdown | Actively maintained by Contentful |
contentful-html-rich-text-converter |
Community npm package | HTML | Limited support for tables, nested lists; no inline style handling; does not validate against Contentful schema | Low activity (last commit 2022+) |
contentful-import CLI |
Official CLI tool | Contentful JSON export format | Requires pre-transformed JSON; no HTML parsing; ideal for the load phase after transformation | Actively maintained by Contentful |
Custom HTML → AST parser (cheerio/jsdom) |
Custom build | Any HTML | Build time required; full control over edge cases | N/A — you own it |
Recommendation: Use contentful-import for the load phase (it accepts a well-structured JSON file and handles rate limiting internally). Build a custom parser for the HTML → Rich Text AST transformation phase. The community converter is not recommended for production migrations due to schema validation gaps.
Conversion options
@contentful/rich-text-from-markdown — Handles paragraphs, headings, emphasis, strong, links, lists, blockquotes, tables, and code blocks. Images require a custom callback. If your Kentico content is Markdown-based (unlikely for most KX13 sites), this is the cleanest path. For HTML content, you would first need to convert HTML to Markdown using a tool like turndown, which introduces a second transformation layer and additional error surface.
Custom HTML → AST parser — The most reliable approach for complex Kentico content. Parse HTML with a library like cheerio or jsdom, walk the DOM tree, and emit Contentful Rich Text nodes. This gives you full control over how Kentico-specific patterns (widget markup, inline macros, custom elements) get mapped.
Your migration middleware must:
- Load the Kentico HTML string into an HTML parser.
- Strip out unsupported Kentico inline macros or replace them with static text.
- Identify
<img>tags and<a>tags pointing to internal Kentico resources. - Walk the DOM tree and map standard HTML tags (
<h1>,<p>,<strong>) to their corresponding ContentfulnodeTypeobjects. - Rebuild internal links using Contentful's
entry-hyperlinkorasset-hyperlinknode types, which requires knowing the Contentful Entry ID of the linked target.
Edge cases that break conversions
- Inline images in HTML — Contentful Rich Text supports
embedded-asset-blockbut not inline images within a paragraph. Images must be block-level. Any<img>inside a<p>needs to be extracted and placed as a sibling block. - Tables — Contentful Rich Text supports tables natively, but nested tables or tables with
colspan/rowspanare not supported. Complex Kentico tables may need restructuring. - Widget markup — KX13 page builder widget data is stored as JSON in
CMS_Document. These are layout/presentation constructs with no content equivalent in Contentful. Extract the content from widget data; discard the layout metadata. - Embedded media with inline styles — Contentful strips inline styles. If your Kentico content uses inline
styleattributes for layout (float, width), those are lost. - Rich Text size limit — Contentful enforces a ~1 MB limit on Rich Text fields. Pages with extremely long body content may need to be split across multiple entries or fields.
CMA error taxonomy for Rich Text failures
When the CMA rejects an entry, it returns a 422 Unprocessable Entity with a structured error body. The following are the most common errors in migration context:
| CMA Error | Root Cause | Resolution |
|---|---|---|
invalid_entry / INVALID_RICH_TEXT |
Rich Text AST node has an unrecognized nodeType |
Check for unsupported node types; Kentico widget markup or custom HTML elements often produce these |
INVALID_RICH_TEXT_MARKS |
Mark type not in allowed set (bold, italic, underline, code, superscript, subscript) |
Strip or remap custom mark types; inline <span style="color:red"> has no valid mark |
INVALID_RICH_TEXT_EMBEDDED_ENTRY |
Referenced entry sys.id does not exist or is not published |
Import dependency ordering violated; ensure referenced entries exist before the linking entry |
RICH_TEXT_TOO_LARGE |
Serialized Rich Text field exceeds ~1 MB | Split content across multiple entries or multiple Rich Text fields |
LINKED_ENTRY_NOT_FOUND |
A Link field references a sys.id that was not created |
Dependency ordering failure; rebuild import sequence or pre-validate ID map |
VERSION_MISMATCH |
PUT request on update specifies wrong sys.version |
Re-fetch the entry to get current version before updating (critical in delta sync) |
TOO_MANY_REQUESTS (429) |
Rate limit exceeded | Read X-Contentful-RateLimit-Reset header; pause for specified seconds before retry |
How to Handle Assets and Media Library Files
Contentful treats every image or document as an Asset. Migrating media from Kentico requires a multi-step API sequence:
- Extract the binary — Download the file from the live Kentico environment, the underlying filesystem, or Azure Blob Storage.
- Create the Asset — Send a POST request to the Contentful CMA with the file's metadata (title, description) and either a publicly accessible upload URL or direct binary data.
- Process the Asset — Trigger the
/processendpoint so Contentful downloads the file, generates thumbnails, and distributes it to the CDN. - Publish the Asset — Send a final request to publish the Asset so it becomes accessible via the delivery API.
Each step is a separate API call. At 7–10 requests per second (depending on plan tier), uploading 1,000 media files requires a minimum of 4,000 API calls — approximately 7–10 minutes of pure API time at maximum throughput, before accounting for asset processing latency, which is asynchronous. You must poll the asset status endpoint until sys.status returns published before referencing that asset in an entry.
For Kentico media library files stored on the filesystem, the simplest approach is to host them temporarily on an accessible URL (an S3 bucket or Azure Blob container) and pass the URL to Contentful's asset creation endpoint. For page attachments stored in CMS_Attachment, extract the binary data, write it to a temporary location, and follow the same process.
Asset ID mapping is critical. Build and persist a lookup table mapping Kentico attachment GUIDs and media file paths to Contentful asset sys.id values. You will need this to resolve image references inside Rich Text fields and reference fields during entry creation.
Because content entries depend on asset IDs for Rich Text embedded images and reference fields, media migration must always happen before content migration.
How to Load Entries into Contentful via the CMA
Official tooling: contentful-import
Contentful's official contentful-import CLI tool accepts a JSON file in Contentful's export format and handles the full create-and-publish sequence, including basic retry logic. It is the recommended load mechanism when your transformation output can be structured as Contentful JSON.
contentful-import \
--space-id YOUR_SPACE_ID \
--environment-id sandbox \
--management-token YOUR_CMA_TOKEN \
--content-file ./transformed-output.jsonThe tool respects dependency ordering within a single import file if entries are sorted correctly. For large datasets, split the import file by content type and run assets first, then independent types, then dependent types. The tool does not handle Kentico-specific extraction or HTML transformation — it is load-only.
Rate limits
The Contentful Content Management API enforces a default rate limit of 7 requests per second on free plans and 10 requests per second on paid plans (verified against Contentful's published API documentation). This is a per-space limit shared by all clients — including the Contentful web app itself. Running a migration script while editors are working in the same space will degrade their experience.
Your migration script must implement:
- Throttling: Use a task queue or a library like
p-limitin Node.js to cap concurrent requests below the rate limit. - Retry logic: When a 429 error occurs, read the
X-Contentful-RateLimit-Resetheader. Pause the script for the exact number of seconds specified before retrying. - Failure logging: Log every failure with the source record ID for re-processing.
Best practice: Run migrations against a sandbox environment, not master. Contentful environments let you create isolated copies for testing. Migrate into a sandbox, validate, then promote using environment aliasing. Environment aliasing works by pointing a named alias (e.g., master) to a specific environment ID — you promote by updating the alias target, making the switch atomic from the delivery API's perspective with no downtime.
Dependency ordering
Contentful entries cannot reference other entries that do not yet exist. If a BlogPost entry links to an Author entry, the author must be created and published first.
The correct import order is:
- Assets — Upload, process, and publish all media first.
- Independent content types — Authors, categories, tags — entries with no outbound references.
- Dependent content types — Articles, pages — entries that reference other entries or assets.
- Publish — Entries must be explicitly published after creation. A created-but-unpublished entry exists in draft state and will not appear in delivery API responses.
Skipping this ordering produces LINKED_ENTRY_NOT_FOUND or UnresolvedLinks errors on publish.
Batch timing benchmarks
At 10 requests/second on a paid plan, with 2 API calls per entry (create + publish):
| Content Volume | Minimum API Time | Realistic Time (with retries + processing) |
|---|---|---|
| 500 entries | ~1.7 minutes | ~5–10 minutes |
| 5,000 entries | ~17 minutes | ~45–90 minutes |
| 20,000 entries | ~67 minutes | ~3–5 hours |
| 1,000 assets | ~7 minutes API time | ~20–40 minutes (async processing adds latency) |
Real-world throughput is lower than theoretical maximums because 429 retries add wait time (typically 1–10 seconds per retry), asset processing is asynchronous and variable, and validation errors on individual entries require logging, skipping, and re-queuing.
What Does Not Migrate Cleanly
Some Kentico features have no Contentful equivalent. Understand what you will lose before you start:
| Kentico Feature | Contentful Status | What to Do |
|---|---|---|
| Page templates / layouts | No equivalent | Rebuild in your frontend framework |
| Page builder widgets | No equivalent | Extract content from widget JSON; discard layout |
| Workflows (approval chains) | Basic workflows on paid plans | Recreate manually; Contentful workflows are simpler |
| Custom modules | No equivalent | Evaluate if data belongs in Contentful or an external system |
| Form data (BizForms) | No equivalent | Migrate to a forms service (Typeform, HubSpot, etc.) |
| E-commerce (SKUs, orders) | No equivalent | Migrate to a commerce platform (Shopify, Commerce Layer, etc.) |
| User accounts / membership | No equivalent | External identity provider |
| URL aliases / routing rules | No built-in routing | Implement in frontend or CDN layer |
| Scheduled publishing | Supported (paid plans) | Available on Lite and above |
| A/B testing / personalization | Contentful Personalization (paid) | Separate product, requires Enterprise |
Multilingual Content: How Locales Map
Kentico stores each language version as a separate CMS_Document record linked to the same CMS_Tree node via DocumentNodeID. Contentful uses field-level localization — a single entry contains values for all locales in each field.
Your import script must group all culture versions of a Kentico page into a single Contentful entry creation call with locale-specific field values:
const entry = {
fields: {
title: {
'en-US': 'Article Title',
'de-DE': 'Artikeltitel'
},
body: {
'en-US': richTextDocEN,
'de-DE': richTextDocDE
}
}
};Contentful requires locales to be configured in the space before import. The free plan supports 2 locales, Lite supports 3, and Enterprise supports more (verified against Contentful's published plan limits). If your Kentico site has more culture versions than your Contentful plan allows, you will need to upgrade or split content across spaces.
Validation and Cutover Strategy
Never trust a migration until you have validated it programmatically.
Record-count parity: Compare entry counts per content type in Contentful against page counts per page type in Kentico. Mismatches indicate dropped records — usually caused by validation errors, malformed HTML, or unresolved references.
Field-level validation: Spot-check a sample of entries across every content type. Compare source field values against Contentful entry fields. Pay particular attention to Rich Text fields where conversion may have dropped elements.
Referential integrity: Verify that all entry references resolve. A broken link in Contentful is an entry reference pointing to a sys.id that does not exist — this will cause frontend errors if published. Query the Contentful CMA for entries in draft state; an entry that failed validation during publish will remain in draft.
Asset verification: Confirm all assets are in published state and their URLs resolve. Contentful's asset processing is async — an asset can exist in the space without being processed or published. Filter assets by sys.publishedAt is null to find unprocessed assets.
Redirect map: Export NodeAliasPath from Kentico and map it to the URL structure in your new frontend. Publish 301 redirects at cutover. Kentico URLs often follow the tree path (/Products/Widget-A); Contentful has no URL concept — your frontend defines routing.
A background sync approach keeps the Kentico source system operational during validation. Run the bulk migration, validate in a sandbox environment, fix issues, perform a delta sync (using DocumentModifiedWhen as the change-detection field), then promote the environment alias from the sandbox to master with no downtime.
How Long Does a Kentico to Contentful Data Migration Take?
The data migration itself — extracting from Kentico, transforming content, and loading into Contentful — typically falls within 1–5 business days for most sites. This depends on data volume, content complexity, the number of page types, and Contentful's CMA rate limits.
Small datasets under 10,000 records can finish in under 24 hours. A content-heavy Kentico site with 5,000+ pages, complex rich text, and thousands of media files is a custom engagement — typically an initial bulk migration followed by delta syncs, running 7–13+ business days depending on API rate limits, data complexity, and the customer's own availability for validation.
These numbers describe the data migration only. They do not describe the time to rebuild your frontend, configure editorial workflows in Contentful, or reimplement integrations. We recommend starting the scoping conversation at least 3–4 months before your internal deadline, especially if you are working against the KX13 end-of-support date.
Kentico Xperience 13 End-of-Support Context
Kentico Xperience 13 reaches end of support on December 31, 2026. From January 1, 2027, Kentico provides no security patches, hotfixes, or technical support. KX13 has already been in security-only support since January 2026 — no new features, no functional bug fixes.
The platform continues to run after end of support; it is not switched off. But running unsupported software exposes your organization to unpatched vulnerabilities and compliance risk, particularly if you handle customer data or payments.
Kentico's recommended path is to upgrade to Xperience by Kentico. Migrating to Contentful instead is a fundamentally different decision — it is a replatform, not an upgrade. For teams evaluating that option, see What Kentico's Migration Tool Doesn't Move (KX13 → XbyK) and How to Export Data from Kentico for extraction specifics. If you are still evaluating target platforms, we have a detailed comparison of Contentful alternatives, as well as dedicated migration guides for Sitecore, Optimizely, Umbraco, and WordPress.
When to Use ClonePartner for This Migration
A Kentico-to-Contentful migration is a pipeline engineering problem: SQL extraction, HTML-to-Rich-Text-AST conversion, asset processing, rate limit management, dependency ordering, and multi-pass validation.
Our process:
- Connect to your source and target accounts.
- Build a custom extraction and transformation pipeline mapping Kentico page types to Contentful content types.
- Provide unlimited sample migrations until the data structure is right.
- Execute the full migration, followed by delta syncs to catch last-minute content changes.
One fixed price per project starting at $500 — no hourly billing, no per-record metering. A dedicated migration engineer owns your project from start to finish. Our transfer preference is API > JSON > CSV. For Kentico, that typically means direct SQL or API extraction on the source side and CMA ingestion on the Contentful side. We handle the Rich Text conversion, asset mapping, locale merging, and validation — the parts where migrations break.
Frequently Asked Questions
- Can I migrate directly from Kentico to Contentful?
- There is no off-the-shelf migration connector between Kentico and Contentful. You need a custom ETL pipeline that extracts content from Kentico's SQL Server database (or REST API), converts HTML body content to Contentful's Rich Text JSON AST format, uploads media as Contentful Assets, and creates entries via the Content Management API.
- How do I convert Kentico HTML to Contentful Rich Text?
- Contentful Rich Text is a JSON AST, not HTML. You can use the @contentful/rich-text-from-markdown npm package for Markdown content, or parse HTML with a library like cheerio or jsdom and emit Rich Text nodes programmatically. A custom parser gives the most control over edge cases like inline images, widget markup, and nested tables.
- What are Contentful's CMA rate limits for migration?
- The Contentful Content Management API enforces a rate limit of 7 requests per second on the free plan and 10 requests per second on paid plans. This is a per-space limit shared across all clients. Creating and publishing 5,000 entries takes roughly 8–9 minutes of pure API time at the paid plan rate, before accounting for retries and asset processing.
- How long does a Kentico to Contentful data migration take?
- The data migration itself typically takes 1–5 business days for most sites, depending on data volume, content complexity, and API rate limits. Small datasets under 10,000 records can finish in under 24 hours. This timeframe covers the data migration only — not rebuilding frontend templates, integrations, or editorial workflows, which is a separate project.
- Does Kentico Xperience 13 still work after end of support?
- Yes. Kentico Xperience 13 reaches end of support on December 31, 2026 — not end of life. The platform continues to run, but Kentico will no longer provide security patches, hotfixes, or technical support from January 1, 2027. Running unsupported software carries increasing security and compliance risk.