Launched:self-serve migrations intoSuperhuman Docs (Coda)
Try it now
01Agent-first
Runs where you already work
Plug it into Claude, ChatGPT or Cursor. Describe the move in plain English; the agent runs it.
02Engineer-led
Our production engine, unlocked
The pipeline our engineers use on managed enterprise migrations — the same code, now something you can drive yourself.
03Pricing
Try 10 pages free, then $1 a page
Credit-based, pay-as-you-go. No scoping call, no quote — sample it on your own docs before you spend anything.
04Sources
NotionSlabConfluenceSoonGoogle DocsSoon
Skip to content

Kentico to Sitecore Migration: A Technical Guide

A technical guide to migrating content from Kentico Xperience 13 to Sitecore XM Cloud or XP — covering SQL extraction, content model mapping, import APIs, and what breaks.

Rishabh Makhar Rishabh Makhar · · 22 min read
Kentico to Sitecore Migration: A Technical Guide
TALK TO AN ENGINEER

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 Sitecore Migration: A Technical Guide

Migrating from Kentico (Xperience 13 or older) to Sitecore is a custom extraction, transformation, and loading (ETL) operation. No native migration connector exists between the two platforms — no import wizard, no vendor-provided tool, no drag-and-drop bridge. Kentico's own Migration Toolkit supports inbound migrations to Xperience by Kentico from Sitecore, but not the reverse direction.

Kentico stores content in a highly relational SQL database split across tree, document, and custom page-type tables. Sitecore stores content as items in a hierarchical content tree, defined by templates, with a separate presentation layer. Moving between them requires translating relational data into Sitecore's item-based architecture — a fundamentally different content model.

Teams typically pursue this migration when consolidating on Sitecore's enterprise personalization engine, adopting headless delivery via Sitecore XM Cloud and Experience Edge, or responding to the Kentico Xperience 13 end of support deadline (December 31, 2026). The trade-off is real: you leave behind Kentico's faster time-to-launch and simpler editorial experience and adopt Sitecore's deeper flexibility at the cost of higher infrastructure complexity, licensing cost, and implementation overhead.

This guide covers extraction methods from Kentico, Sitecore's import pathways, content model mapping, what breaks during the move, target platform selection (XM Cloud vs. XP), and practical timelines.

Warning

Two deadlines are converging. Kentico Xperience 13 reaches end of support on December 31, 2026 — no security patches, no hotfixes, no vendor support after that date. Sitecore XP 10.0 and 10.1 Extended Support also ends December 31, 2026. If you're leaving KX13 for Sitecore, target a version with a real support runway: XM Cloud, XP 10.4 (Extended Support through 2030), or XP 10.5 (Mainstream Support through 2029). For the full version-by-version breakdown, see our Sitecore XP End of Support guide.

Why Teams Move From Kentico to Sitecore

The most common drivers across migration engagements:

  • Enterprise personalization at scale. Kentico Xperience 13 has marketing automation and contact tracking, but Sitecore's rules engine, xDB analytics, and session-level personalization are deeper and more configurable for large B2C and B2B operations.
  • Headless and composable delivery. Sitecore XM Cloud is a SaaS headless CMS with Experience Edge for CDN-backed content delivery via GraphQL. Teams building Next.js or React front-ends often prefer Sitecore's headless-first architecture over KX13's MVC-era rendering pipeline.
  • Multi-site governance. Sitecore's content tree, multi-site tenancy, and granular role-based access control are built for organizations running 10+ sites under centralized editorial governance.
  • Ecosystem standardization. An enterprise already uses Sitecore elsewhere and wants to consolidate on a single platform.

Kentico's strengths — faster time-to-launch, lower TCO for mid-market, simpler editorial experience — are real advantages. This migration only makes sense when you've genuinely outgrown what KX13 can deliver, or when the end-of-support deadline forces a platform decision and Sitecore fits the forward architecture.

Which Kentico Versions Does This Cover?

Kentico Xperience 13 is the version most teams are migrating from. It reaches end of technical support on December 31, 2026. From January 1, 2027, Kentico will deliver no product updates, no security hotfixes, and no technical support. KX13 has been in security-only support since January 1, 2026: no new features, no functional bug fixes, only security hotfixes through end of life.

Older versions — Kentico 12, 11, and earlier — are already past end of support. The extraction techniques in this guide apply to all of them (the database schema is structurally consistent), but KX13 is the focus because it represents the active migration wave.

The Architecture Mismatch Between Kentico and Sitecore

A direct 1:1 migration is impossible because the underlying architectures model content differently. Understanding this gap is essential before writing any migration code.

Concept Kentico (KX13) Sitecore (XM Cloud / XP)
Content storage SQL Server: CMS_Tree + CMS_Document + coupled data tables per page type Items in a hierarchical content tree, stored in SQL (XP) or managed via APIs (XM Cloud)
Content types Page types with coupled data tables (e.g., DancingGoat_Article) Templates with field sections; items inherit from templates
Presentation Page Builder widgets + MVC views (KX13) or Portal Engine (older) Renderings, layouts, and components; SXA for XM Cloud
Media Media libraries (filesystem or Azure Blob) + page attachments (database) Media Library items in content tree (XP) or Content Hub / Edge media (XM Cloud)
Taxonomy Categories bound to CMS_Document + tags Taxonomy items in content tree; tag fields
Relationships CMS_Relationship table (page-to-page) Item references via link/reference fields
Multilingual Multiple CMS_Document rows per node (one per culture) Language versions per item

Kentico's content model splits every page across at least three tables:

  • CMS_Tree stores the hierarchy — node order, parent-child relationships, NodeGUID, and NodeClassID.
  • CMS_Document stores the versioned content — culture (language) variants, workflow state (DocumentWorkflowStepID), publish dates, and DocumentModifiedWhen (critical for delta syncs).
  • Coupled data tables (e.g., CONTENT_Article or DancingGoat_Article) store the custom fields specific to that page type.

Sitecore's content model is item-first. Everything — pages, media, configuration, templates — is an Item. An Item inherits from a Template, which defines its fields. Items are organized in a strict tree under /sitecore/content.

The core migration task: flatten Kentico's three-table join into a structured payload, then push that payload into Sitecore as Items mapped to specific Templates.

How to Extract Content From Kentico

The best extraction method depends on your Kentico version, data volume, and whether you have direct database access. For a comprehensive breakdown, see our Kentico data export guide.

Direct SQL access is the most reliable extraction path for cross-platform migrations. It bypasses the application layer, avoids API rate limits, and lets you join the exact tables needed to build a comprehensive payload.

The core query pattern joins the tree, document, and coupled data tables:

SELECT 
  t.NodeID,
  t.NodeParentID,
  t.NodeAliasPath,
  t.NodeGUID,
  t.NodeClassID,
  d.DocumentName,
  d.DocumentCulture,
  d.DocumentPublishFrom,
  d.DocumentPublishTo,
  d.DocumentModifiedWhen,
  d.DocumentWorkflowStepID,
  c.ArticleTitle,
  c.ArticleBody,
  c.PublishDate
FROM CMS_Tree t
INNER JOIN CMS_Document d ON d.DocumentNodeID = t.NodeID
INNER JOIN CONTENT_Article c 
  ON c.ArticleID = d.DocumentForeignKeyValue
WHERE t.NodeSiteID = 1 
  AND d.DocumentCulture = 'en-US'
ORDER BY t.NodeAliasPath

You need to repeat this pattern for every page type (coupled data table) in your content model. The CMS_Class table tells you which page types exist and what their coupled table names are.

What SQL extraction gives you that other methods don't:

  • Complete access to all language versions, workflow states (DocumentWorkflowStepID), and full version history
  • DocumentModifiedWhen timestamps — essential for delta sync scoping
  • No API rate limits or pagination constraints
  • Access to CMS_Relationship for page-to-page links
  • Access to CMS_Attachment for database-stored file attachments
  • Access to CMS_Category and CMS_DocumentCategory for taxonomy

The Kentico REST API

Kentico's built-in REST service exposes page and object data over HTTP, supporting both XML and JSON responses with Basic Authentication. It works for targeted, small-volume extractions or validation checks, but has significant limitations for bulk migration:

  • No pagination for page queries. You can filter by page type using ?classnames=cms.article, but there is no native cursor or offset-based pagination for pages.
  • Coupled data requires explicit opt-in. Append ?coupleddata=true to include page-type-specific fields.
  • Rate and performance impact. Heavy extraction can degrade the live Kentico application.
  • Security surface. The REST service must be explicitly enabled and exposes database structure directly over HTTP.

The Site Export Wizard

Kentico's Site Export Wizard produces a proprietary ZIP package containing XML-serialized content. This format is designed exclusively for import into another Kentico instance. It cannot be ingested by Sitecore. The XML schema is highly proprietary, lacks clear relational mapping for custom page types, and exports the full content tree with no option to select individual branches. Do not use this for a Sitecore migration.

Mapping Kentico Page Types to Sitecore Templates

Data mapping is the most labor-intensive planning step. Every Kentico page type must be mapped to a corresponding Sitecore template before any data moves.

Auditing the Kentico content model

Start by querying CMS_Class to inventory all page types, their coupled table names, and record counts:

SELECT 
  ClassName,
  ClassDisplayName,
  ClassTableName,
  ClassIsDocumentType,
  (SELECT COUNT(*) FROM CMS_Tree WHERE NodeClassID = ClassID) AS PageCount
FROM CMS_Class
WHERE ClassIsDocumentType = 1
ORDER BY PageCount DESC

This tells you exactly what you're dealing with and which page types carry the most content.

Field type mapping

For each Kentico page type, create a Sitecore template with matching fields. The field types don't map 1:1 — here's the translation layer:

Kentico Field Type Sitecore Field Type Notes
Text (varchar) Single-Line Text
Long text (nvarchar max) Rich Text / Multi-Line Text Check if the field contains HTML or plain text
Date and time Datetime
Boolean Checkbox
Integer Integer
Decimal Number
File (attachment) Image / File Requires separate media upload first
Page selector Droptree / General Link GUID-based reference; needs remapping
Multiple choice Checklist / Multilist Depends on Sitecore data source

Content tree mapping

Kentico's NodeAliasPath defines the tree hierarchy. Sitecore's content tree has a similar concept but with different root structures. A typical mapping: Kentico's /Articles/2024/my-post becomes /sitecore/content/Site/Home/Articles/2024/my-post in Sitecore.

Important: Item buckets for high-volume content. Sitecore's standard content tree degrades at scale — Sitecore recommends enabling Item Buckets for containers holding more than 100 child items. A migration of 10,000+ articles into a flat tree node will cause severe performance problems in the Content Editor. Configure bucket templates and the bucket folder structure before running ingestion scripts, not after. Bucketed items use a yyyy/mm/dd/hh/mm auto-folder path, so your ingestion code must target the bucket container, not a specific subfolder.

Handling GUIDs and referential integrity

Kentico identifies nodes using a NodeGUID. Sitecore identifies items using an Item ID (also a GUID). How GUIDs carry over depends entirely on your ingestion method:

  • Sitecore PowerShell Extensions (XP only): You can explicitly set the Sitecore Item ID to match the Kentico NodeGUID, which automatically preserves internal relationships. If Page A linked to Page B via a GUID in Kentico, that link resolves in Sitecore without a mapping table.
  • Sitecore CLI serialization: Serialized YAML files preserve item GUIDs. You'd need to generate Sitecore-compatible YAML from Kentico's extracted data — doable but adds a format conversion step.
  • Sitecore GraphQL API: The Authoring and Management GraphQL API does not preserve item GUIDs. Every item created gets a new GUID from Sitecore. You must maintain a mapping table of old Kentico GUIDs to new Sitecore item IDs and rewrite all internal references post-import.

If you're targeting XM Cloud (where SPE is unavailable), the GUID remapping step is unavoidable.

The GUID mapping table is a concrete SQL staging table you build and maintain throughout the migration. Schema:

CREATE TABLE migration_guid_map (
  kentico_node_guid    UNIQUEIDENTIFIER NOT NULL,
  kentico_alias_path   NVARCHAR(2000)   NOT NULL,
  sitecore_item_id     UNIQUEIDENTIFIER NULL,       -- populated after ingestion
  sitecore_item_path   NVARCHAR(2000)   NULL,
  migrated_at          DATETIME         NULL,
  PRIMARY KEY (kentico_node_guid)
);

Populate kentico_node_guid and kentico_alias_path during extraction. After each GraphQL createItem mutation returns an itemId, write it back to sitecore_item_id. During the rich text rewrite pass, look up every Kentico GUID found in ~/getmedia/ or ~/getdoc/ URLs against this table to retrieve the correct Sitecore item ID before generating the output link.

Handling Kentico Page Builder widgets

If your Kentico instance uses the MVC Page Builder, you face a significant challenge. Kentico stores widget configurations as a serialized JSON string in the DocumentPageBuilderWidgets field. The structure looks like this:

{
  "zones": [
    {
      "identifier": "main-zone",
      "widgets": [
        {
          "identifier": "abc123",
          "type": {
            "identifier": "DancingGoat.HeroImage"
          },
          "properties": [
            {
              "value": {
                "Heading": "Welcome to our site",
                "ImageGuid": "12345678-1234-1234-1234-123456789012"
              }
            }
          ]
        }
      ]
    }
  ]
}

Each widget has a type.identifier (the registered widget code name), zone placement, and a properties array containing the actual field values. To audit all widget types present across your content tree before migration, run:

SELECT DISTINCT 
  w.type_identifier,
  COUNT(*) AS usage_count
FROM CMS_Document d
CROSS APPLY OPENJSON(d.DocumentPageBuilderWidgets, '$.zones[*].widgets[*]')
  WITH (type_identifier NVARCHAR(200) '$.type.identifier') w
WHERE d.DocumentPageBuilderWidgets IS NOT NULL
GROUP BY w.type_identifier
ORDER BY usage_count DESC

This inventory tells you exactly how many distinct widget types need handling before you write a single transformation rule.

Sitecore manages layouts via presentation details (the __Renderings field), which uses its own XML-based layout engine. There is zero compatibility. You cannot map Kentico widgets directly to Sitecore components. You must parse the Kentico widget JSON, extract the raw content (text, image paths), and either:

  1. Map it into standard Sitecore Rich Text fields.
  2. Programmatically generate Sitecore layout XML to assign specific Sitecore components — this requires mapping Kentico widget type identifiers to Sitecore rendering item IDs and is highly complex.

Every widget rendering must be rebuilt from scratch in Sitecore's presentation layer. The migration script extracts widget data (field values, configuration), but the rendering code is a full rewrite.

Workflow state mapping

Kentico's workflow engine assigns each document a DocumentWorkflowStepID that references a step in a configured workflow (draft, review, approved, published). Sitecore has its own workflow system with different step structures. Before running ingestion:

  1. Query CMS_WorkflowStep to enumerate Kentico workflow states present in your content.
  2. Decide which Sitecore workflow state each maps to — typically: Kentico "Published" → Sitecore "Final" state; Kentico "Draft" or "Review" → Sitecore "Draft" state.
  3. Configure the corresponding Sitecore workflow and states in the target instance before ingestion, so your scripts can set __Workflow and __Workflow state fields on items during creation.
  4. Decide whether to migrate unpublished/draft content at all — many migrations choose to import only published (DocumentWorkflowStepID corresponding to a published step) and leave drafts behind.

Failing to handle workflow state means all migrated items land in Sitecore's default workflow state (often requiring manual re-approval for hundreds or thousands of items).

How to Migrate the Kentico Media Library

Media migration must occur before page migration. Sitecore pages cannot link to images that don't yet exist in the Sitecore Media Library.

Extraction

Media files in Kentico come from three sources:

  • Media libraries: Files on the filesystem (typically under /App_Data/MediaFiles/ or Azure Blob Storage). Copy directly.
  • Page attachments: Binary data stored in the CMS_Attachment table (common in legacy builds). Extract via SQL and write to disk.
  • Inline images in rich text: Parse HTML fields for /getmedia/ and /getattachment/ URLs. These need to be rewritten after import.

Extract the binaries along with their metadata: alt text, title, extension, and GUID (AttachmentGUID or FileGUID).

Ingestion

Upload binaries into the Sitecore Media Library. If you're using SPE on Sitecore XP, force the Sitecore Media Item ID to match the Kentico GUID to maintain referential integrity. If you're using the GraphQL API on XM Cloud, you must maintain a GUID mapping table instead (using the same migration_guid_map schema described above, extended with a media_source column to distinguish page items from media items).

XM Cloud media size limit: Experience Edge enforces a 50 MB per-file limit. Files exceeding this threshold must be hosted externally (e.g., Sitecore Content Hub DAM, Azure CDN, or a third-party DAM) and referenced via absolute URL rather than uploaded to the Sitecore Media Library.

XM Cloud and Content Hub DAM: If your XM Cloud implementation includes Sitecore Content Hub DAM, consider routing large or frequently reused media assets there rather than to the built-in Media Library. Content Hub provides asset versioning, rights management, and CDN delivery that the built-in Media Library does not. This decision must be made before ingestion — retrofitting media routing post-migration requires re-running media uploads and rewriting all references again.

Validating media integrity

After upload, verify binaries were not corrupted during transfer by comparing file hashes:

-- Kentico: extract file hash from CMS_MediaFile
SELECT FileGUID, FileName, FileMimeType, FileSize
FROM CMS_MediaFile
WHERE FileLibraryID = @LibraryID

Compare FileSize values between the Kentico source and the Sitecore Media Library item. For critical assets (PDFs, high-resolution images), also compare MD5/SHA-256 checksums computed from the binary stream.

Kentico rich text fields contain internal URLs like:

~/getattachment/12345678-1234-1234-1234-123456789012/image.jpg

Sitecore rich text fields expect dynamic link syntax:

<image mediaid="{12345678-1234-1234-1234-123456789012}" /> (for images) <a href="~/link.aspx?_id={ITEM-GUID}&amp;_z=z">text</a> (for general links)

During transformation, scan all rich text fields to locate Kentico getattachment, getdoc, and getmedia URL patterns and replace them with Sitecore's dynamic link syntax. The rewrite logic should:

  1. Parse the HTML field with a proper HTML parser (e.g., HtmlAgilityPack in .NET) — not raw string replacement, which fails on malformed or nested HTML.
  2. Extract every Kentico GUID from matched URL patterns.
  3. Look up each GUID in the migration_guid_map table to retrieve the corresponding Sitecore item ID.
  4. Emit the Sitecore dynamic link format using the resolved Sitecore item ID.
  5. Log any GUID that has no mapping entry — these are broken references that need manual review.

This rewriting step is where most migration bugs hide. A dedicated validation pass after ingestion (scanning all rich text fields in Sitecore for unresolved GUIDs or HTTP 404s) is non-negotiable.

For strategies on handling media references, see our guide on migrating images, attachments, and embeds without broken links.

How to Import Content Into Sitecore

The import method depends on your target Sitecore architecture. The choice has direct consequences for GUID preservation, throughput, and operational complexity — use this decision framework:

Choose your ingestion method:

Condition Recommended Method
Target is XM Cloud Authoring GraphQL API or CLI serialization
Target is XP/XM (on-prem or PaaS), GUID preservation required SPE (fastest, GUID-settable)
Target is XP/XM, no shell access available GraphQL API (10.3+)
Volume < 500 items, one-time transfer Sitecore packages
Migrating from Sitecore XP to XM Cloud (not Kentico) CLI serialization

Sitecore Authoring and Management GraphQL API

The primary programmatic import path for Sitecore 10.3+ and XM Cloud. The API supports creating, updating, and deleting items, uploading media, and triggering publish operations via GraphQL mutations. Official documentation: Sitecore GraphQL Authoring API.

mutation CreateItem {
  createItem(
    input: {
      name: "My-Migrated-Article"
      templateId: "{TEMPLATE-GUID}"
      parent: "{PARENT-GUID}"
      language: "en"
      fields: [
        { name: "Title", value: "My Migrated Article" }
        { name: "Body", value: "<p>Migrated content</p>" }
      ]
    }
  ) {
    item {
      itemId
      name
      path
    }
  }
}

The API requires OAuth2 authentication with a JWT access token. Endpoint: https://<cm-instance>/sitecore/api/authoring/graphql/v1.

Error handling and idempotency: Your ingestion loop will fail partway through on large datasets. Design for idempotency from the start:

  1. Check migration_guid_map before each mutation — if sitecore_item_id is already populated, skip creation and move to field updates.
  2. Wrap each mutation in try/catch; on failure, log the Kentico NodeGUID, error message, and HTTP status to a migration_errors table.
  3. Implement exponential backoff for HTTP 429 (Too Many Requests) responses — start at 1 second, double on each retry, cap at 60 seconds, abandon after 5 retries.
  4. After a failed run, re-execute the script: items already in migration_guid_map are skipped, failed items are retried, and you don't create duplicates.
Info

API Rate Limits: XM Cloud APIs enforce rate limiting. Bulk ingestion scripts must implement exponential backoff and retry logic to handle HTTP 429 errors. Do not run parallel threads without a semaphore — concurrent mutations against the same parent item can cause write conflicts.

Throughput: The GraphQL API processes roughly 200–400 items per minute under typical field loads (10–15 fields per item, rich text under 50 KB). For 10,000 items, budget 25–50 minutes of API time plus transformation overhead. Complex rich text with inline link rewriting adds approximately 30–50% to transformation time.

Sitecore PowerShell Extensions (SPE)

For Sitecore XP or XM (on-prem or PaaS), SPE is the industry standard for data ingestion. It runs PowerShell scripts directly within the Sitecore context, with full access to the item API. Official documentation: Sitecore PowerShell Extensions.

$templateId = "{TEMPLATE-GUID}"
$parentPath = "/sitecore/content/Home/News"
$name = "My-Migrated-Article"
$targetNodeGuid = [System.Guid]::Parse("KENTICO-NODE-GUID-HERE")
 
# Create item with explicit ID matching Kentico NodeGUID
$item = New-Item -Path $parentPath -Name $name -ItemType $templateId -ForceId $targetNodeGuid
 
$item.Editing.BeginEdit()
$item["Title"] = "My Migrated Article"
$item["Body"] = "<p>Migrated rich text content...</p>"
$item["__Workflow"] = "{WORKFLOW-GUID}"
$item["__Workflow state"] = "{WORKFLOW-STATE-GUID}"
$item.Editing.EndEdit()

Note: -ForceId requires SPE 6.2+. Without it, Sitecore assigns a new GUID and you must maintain a mapping table just as you would with the GraphQL API.

Throughput: SPE processes approximately 1,500–3,000 items per minute for simple field structures, running server-side with no HTTP overhead. For rich text-heavy content requiring inline rewrite, throughput drops to roughly 500–1,000 items per minute. SPE is materially faster than the GraphQL API for large on-prem migrations. SPE is not available on XM Cloud — there is no server-side shell access in Sitecore's SaaS offering.

Sitecore CLI and Content Serialization

Sitecore Content Serialization (SCS) converts items to YAML files on disk. The CLI can push serialized items to both XP and XM Cloud instances. Unlike the GraphQL API, serialization preserves item GUIDs. For Kentico-to-Sitecore, you'd need to generate Sitecore-compatible YAML from Kentico's extracted data — doable but adds a format conversion step.

# Example SCS YAML structure for a migrated item
---
ID: "12345678-1234-1234-1234-123456789012"
Parent: "abcdefab-abcd-abcd-abcd-abcdefabcdef"
Template: "TemplateGUID-Goes-Here"
Path: /sitecore/content/Site/Home/Articles/2024/my-post
Languages:
- Language: en
  Fields:
  - ID: "title-field-guid"
    Hint: Title
    Value: My Migrated Article
dotnet sitecore serialization push -n development

This path is best suited for Sitecore-to-Sitecore moves (e.g., XP to XM Cloud). For a Kentico migration, the YAML generation overhead typically makes the GraphQL API or SPE a more practical choice unless GUID preservation on XM Cloud is a hard requirement.

Sitecore packages

Sitecore packages (.zip format) can bundle items for manual import via the Installation Wizard. Suitable for small, one-time transfers of under 500 items — not for automated, repeatable migrations of thousands of items.

What Breaks During a Kentico-to-Sitecore Migration

Every cross-platform CMS migration has things that don't transfer cleanly. Budget for these.

Personalization and marketing automation

Kentico's contact groups, personas, scoring rules, marketing automation workflows, and A/B test results are stored in KX13-specific tables with KX13-specific logic. None of this transfers to Sitecore. You'll need to recreate personalization rules in Sitecore's rules engine, rebuild marketing automation workflows, and accept that historical analytics data stays behind. If xDB personalization is a primary migration driver, plan 4–8 additional weeks for rules engine configuration and testing after the data migration completes.

Forms

Kentico's built-in forms (BizForms) store form definitions in CMS_Form and submission data in BizForm_<FormCodeName> tables. Sitecore Forms is a separate module with its own schema — form definitions must be rebuilt manually in Sitecore. Historical submission data can be exported to CSV from the BizForm_* tables but won't import directly into Sitecore Forms' submission store. Preserve historical submission exports in a separate reporting database if compliance or audit requirements apply.

URL structure and redirects

Kentico generates URLs from NodeAliasPath. Sitecore generates URLs from the content tree path plus item name. Unless you carefully mirror the Kentico tree structure, URLs will change. Build a redirect map from every old Kentico URL to the new Sitecore URL before cutover. For SEO continuity, 301 redirects are non-negotiable. Generate the redirect list by joining CMS_Tree.NodeAliasPath (source) against the sitecore_item_path column in your migration_guid_map table (target) for every migrated item.

Multilingual content

Kentico stores one CMS_Document row per language version per page. Sitecore stores language versions within the same item. The structural mapping is straightforward, but you need to import all language versions in the correct sequence (default language first, then alternates) and verify field-level language fallback settings on the Sitecore side before running multilingual imports.

Delta Sync: Capturing Content Changes After Initial Extraction

A delta sync captures content published in Kentico after the initial bulk extraction — essential when the Sitecore build takes weeks or months while editors continue publishing to the live Kentico site.

Mechanism: Kentico's CMS_Document.DocumentModifiedWhen column is a reliable change timestamp. A delta sync query filters for documents modified after the last extraction run:

SELECT 
  t.NodeGUID,
  t.NodeAliasPath,
  d.DocumentCulture,
  d.DocumentModifiedWhen,
  d.DocumentWorkflowStepID
FROM CMS_Tree t
INNER JOIN CMS_Document d ON d.DocumentNodeID = t.NodeID
WHERE d.DocumentModifiedWhen > @last_extraction_timestamp
  AND t.NodeSiteID = 1
ORDER BY d.DocumentModifiedWhen ASC

Handling deletes: Kentico does not maintain a delete log in a standard changelog table. To detect deletions, compare the set of NodeGUID values in the current CMS_Tree extract against the kentico_node_guid column in your migration_guid_map table. Any GUID present in the map but absent from the current tree has been deleted in Kentico and should be deleted or unpublished in Sitecore.

Delta sync sequence:

  1. Run the delta query with @last_extraction_timestamp set to the prior extraction's run date.
  2. For each returned node, check migration_guid_map: if sitecore_item_id is populated, run an updateItem mutation; if not, run createItem and populate the map.
  3. Run the delete detection comparison and issue deleteItem mutations for removed content.
  4. Re-run the inline link rewrite pass for any rich text fields in updated items.
  5. Trigger a Sitecore publish for the changed item set.

Run delta syncs nightly during the Sitecore build phase, and run a final delta sync in the 24 hours immediately before cutover to minimize content drift.

Should You Target Sitecore XM Cloud or XP?

Sitecore XM Cloud is Sitecore's SaaS headless CMS — the forward-looking platform. Sitecore XP (Experience Platform) is the on-premises/IaaS option with built-in analytics, personalization, and marketing automation.

Factor XM Cloud XP (10.4 / 10.5)
Hosting Sitecore-managed SaaS Self-hosted (Azure, AWS, or on-prem)
Architecture Headless-only (Next.js / React via JSS) Traditional MVC or headless
Personalization Sitecore Personalize (separate product) Built-in xDB + rules engine
Import API Authoring GraphQL API, CLI serialization GraphQL API (10.3+), SPE, packages, CLI
GUID preservation Not via GraphQL API; possible via CLI serialization Via SPE (-ForceId) or CLI serialization
Media limit 50 MB per file on Edge; larger files need Content Hub or external CDN No hard limit (filesystem-bound)
Item buckets Required for high-volume content; configure before ingestion Required for high-volume content; configure before ingestion
Support runway Evergreen SaaS XP 10.5: Mainstream through Dec 2029

If you're migrating from Kentico and rebuilding your front-end as a headless application, XM Cloud is the natural target. If you're coming from KX13's MVC architecture and want to preserve server-side rendering patterns, XP 10.4 or 10.5 may be a shorter path — but recognize that XP is in maintenance mode and Sitecore's investment is flowing to XM Cloud.

How Long Does the Data Migration Take?

Important distinction: The data migration — extracting content from Kentico and loading it into Sitecore — is a scoped, measurable task. The broader Sitecore implementation project (designing templates, building the front-end, configuring personalization, rebuilding integrations, training editors) is a separate effort that Sitecore implementation partners routinely estimate at 6 to 12 months for an enterprise rebuild. This section covers only the data migration.

By volume, most data migrations complete within 1–5 business days:

  • 1–500 content items: 1–2 business days
  • 500–5,000 content items: 3–7 business days
  • 5,000+ content items: Custom engagement — usually an initial bulk migration followed by nightly delta syncs to capture content published during the Sitecore build. Larger engagements typically run 7–13+ business days for the initial load.

Kentico-to-Sitecore migrations tend toward the upper end of these ranges because of the content model transformation required: field mapping across multiple page types, widget JSON parsing, media URL rewriting, and GUID remapping (especially when targeting XM Cloud where SPE is unavailable).

SQL extraction performance: A full SQL extraction of 50,000 nodes (joining CMS_Tree, CMS_Document, and coupled data tables) typically completes in 5–20 minutes on a modern SQL Server instance with proper indexes on NodeSiteID, DocumentNodeID, and DocumentForeignKeyValue. Extraction of binary attachments from CMS_Attachment adds time proportional to total binary volume — budget approximately 1 GB per 5 minutes over a standard network connection.

Start scoping at least 3–4 months before your internal launch deadline to allow time for content model design, transformation script development, item bucket configuration, and multiple validation cycles.

When This Migration Doesn't Make Sense

  • If your site is under 50 pages and doesn't need personalization, Sitecore's licensing and infrastructure overhead will outweigh the benefits. Consider lighter-weight alternatives like WordPress or Umbraco.
  • If you're on KX13 and just want to stay on Kentico, the upgrade path to Xperience by Kentico using Kentico's own Migration Toolkit is a shorter path than changing vendors entirely. See our guide on what Kentico's migration tool doesn't move.
  • If your KX13 implementation has heavy commerce, Sitecore Commerce is being deprecated in favor of Sitecore OrderCloud — a separate platform requiring its own implementation. The migration surface area doubles.
  • If Sitecore licensing cost is a concern, get a binding quote before starting the migration. Sitecore's pricing varies significantly by tier, module, and usage metrics.

Data Validation and QA

After ingestion, verify the migration with systematic checks:

  1. Record-count parity: Compare the total distinct NodeGUID count in CMS_Tree for the migrated scope against the number of populated rows in migration_guid_map. These must match exactly.
  2. Field-level spot validation: Sample 5–10% of records across each page type. Compare structured fields (dates, booleans, integers) between the Kentico source query result and the Sitecore item field value.
  3. Referential integrity checks: Scan Sitecore rich text fields for any remaining Kentico URL patterns (getmedia, getattachment, getdoc) — these indicate the rewrite pass missed something. Also scan for HTTP 404s by crawling rendered pages.
  4. Media checksums: Compare FileSize between the Kentico CMS_MediaFile table and the Sitecore Media Library item. For high-value assets, compare MD5 checksums of the binary stream.
  5. Multilingual spot-checks: Verify that all expected language versions exist in Sitecore and that language fallback behavior is configured correctly per template.
  6. Workflow state validation: Query Sitecore items for their __Workflow state field and verify the distribution matches expectations (e.g., all migrated items in "Final" state if only published content was imported).
  7. URL redirect validation: Crawl the redirect map and confirm all old Kentico NodeAliasPath URLs return HTTP 301 to their correct Sitecore equivalents. Use a tool like Screaming Frog or a custom script against your staging environment before cutover.
  8. Item bucket integrity: For bucketed content, verify items landed in correctly structured bucket subfolders and are discoverable via Sitecore search.

After validation, run a final delta sync (as described above) to capture content changes made in Kentico since the initial extraction. Cut over DNS, activate 301 redirects, and decommission the Kentico instance.

About This Guide

This guide was produced by ClonePartner, a CMS migration service. We handle the data migration layer — extraction, transformation, and ingestion — as a fixed-scope, fixed-price engagement. We do not build Sitecore templates, develop front-ends, or configure Sitecore personalization; those are implementation-layer concerns handled by Sitecore partners or your internal team.

Our import preference by method: SPE (XP) or GraphQL API (XM Cloud) → JSON intermediate format → validated staging environment. CSV is avoided because it flattens hierarchy and loses field type information.

Security: SOC 2 Type II and ISO 27001 certified, with AES-256 encryption at rest and TLS 1.2+ in transit. Staging data purges within 30 days of project close. Details at trust.clonepartner.com.

Frequently Asked Questions

Is there a migration tool to move from Kentico to Sitecore?
No. Kentico's Migration Toolkit supports inbound migrations to Xperience by Kentico from Sitecore, but not the reverse. Moving from Kentico to Sitecore requires a custom ETL pipeline — typically SQL extraction from Kentico's database, transformation of page types to Sitecore templates, and import via Sitecore's Authoring and Management GraphQL API or PowerShell Extensions.
Does the Sitecore GraphQL API preserve item GUIDs during migration?
No. The Sitecore Authoring and Management GraphQL API creates items with new GUIDs. You must maintain a mapping table of old Kentico GUIDs to new Sitecore item IDs and rewrite all internal references after import. Sitecore CLI serialization does preserve GUIDs but requires content to be in Sitecore's YAML serialization format. Sitecore PowerShell Extensions (XP only) also allow you to set item IDs explicitly.
How do we handle Kentico Page Builder widgets in Sitecore?
Kentico widgets do not map to Sitecore components — there is zero compatibility. You must parse the widget data from the DocumentPageBuilderWidgets JSON field, extract the raw content, and either map it into Sitecore Rich Text fields or programmatically generate Sitecore layout XML. The rendering code must be rebuilt from scratch.
How long does a Kentico to Sitecore data migration take?
The data migration itself (not the broader Sitecore implementation) typically takes 1–5 business days for most datasets. Small datasets under 10,000 records can finish in under 24 hours. Larger engagements with 5,000+ content items run approximately 7–13+ business days. Kentico-to-Sitecore tends toward the upper end due to heavy field mapping and GUID remapping.
Should I migrate to Sitecore XM Cloud or Sitecore XP?
XM Cloud is Sitecore's SaaS headless CMS and the forward-looking platform — best if you're rebuilding the front-end as a headless app. XP (10.4 or 10.5) is on-premises with built-in analytics and personalization, suitable if you want to preserve server-side rendering patterns. XP is in maintenance mode and Sitecore's investment is flowing to XM Cloud.

More from our Blog