---
title: "Kentico to Sitefinity Migration: A Technical Guide"
slug: kentico-to-sitefinity-migration-a-technical-guide
date: 2026-10-12
author: Abdul Aleem
categories: [Migration Guide, Kentico, Sitefinity]
excerpt: "A technical guide to migrating content from Kentico Xperience 13 to Sitefinity CMS — covering data model differences, SQL extraction, OData API import, and SEO preservation."
tldr: Kentico stores pages across three joined SQL tables; Sitefinity imports via OData REST API. Direct SQL extraction plus API writes is the most reliable migration path — no turnkey tool exists.
canonical: https://clonepartner.com/blog/kentico-to-sitefinity-migration-a-technical-guide
---

# Kentico to Sitefinity Migration: A Technical Guide


# Kentico to Sitefinity Migration: A Technical Guide

Migrating from [Kentico Xperience 13](https://docs.kentico.com/13) to [Sitefinity CMS](https://www.progress.com/sitefinity-cms) means moving between two .NET-based content management platforms that share a technology lineage but differ substantially in data architecture, content modeling, and API design. Both are relational, both store structured content — but the way they model pages, handle media, and expose content for programmatic access diverges at every layer.

The short version: **Kentico stores page data across three joined SQL tables (CMS_Tree, CMS_Document, and per-type coupled tables). Sitefinity stores content via a provider model and exposes it through OData REST endpoints that support full CRUD operations.** The most reliable extraction path from Kentico is direct SQL. The most reliable import path into Sitefinity is its OData REST API or the C# REST SDK. There is no turnkey migration tool that bridges these two platforms.

With Kentico Xperience 13 reaching end of support on December 31, 2026, many engineering teams are evaluating Sitefinity, [Sitecore](https://clonepartner.com/blog/blog/kentico-to-sitecore-migration-a-technical-guide), or [Contentful](https://clonepartner.com/blog/blog/kentico-to-contentful-migration-a-technical-guide) as a replacement rather than taking the complex upgrade path to Xperience by Kentico (XbyK). This guide covers the exact data model differences, field-level extraction from Kentico, content import into Sitefinity via API, the content types that don't map cleanly, and the edge cases that will break your migration if you ignore them.

> [!WARNING]
> **KX13 deadline:** Kentico Xperience 13 reaches end of support on **December 31, 2026**. After that date, Kentico provides no hotfixes, security patches, or technical support. The platform keeps running but as fully unsupported software. If you're scoping a migration off KX13, start now — we recommend beginning at least 3–4 months before any internal deadline.

## How Kentico and Sitefinity Store Content Differently

Understanding the data model gap is the prerequisite for every migration decision that follows.

### Kentico's three-table page architecture

Kentico stores pages across several interconnected database tables. The three you care about for migration:

- **CMS_Tree** — One record per page, regardless of language versions. Holds the content tree position (`NodeAliasPath`, `NodeParentID`, `NodeOrder`) and properties shared across all cultures. This table does not store versioned data.
- **CMS_Document** — Page properties that have unique values for each language version, including the page builder widget data stored in `DocumentPageBuilderWidgets` as JSON. Multiple records per page (one per language).
- **Coupled data tables** — Stores the fields of individual page types. For example, the News page type has the `CONTENT_News` coupled table with columns defined for news pages, such as `NewsTitle`, `NewsSummary`, `NewsText`. These tables hold your actual custom content fields.

Records in the coupled data tables are bound to pages through the `DocumentForeignKeyValue` column of the CMS_Document table. This three-way join is the reason you can't just export one table and call it done.

The URL structure is inherently tied to the node's position in the tree via `NodeAliasPath`. This matters during URL redirect planning.

### Sitefinity's provider model and Module Builder

Sitefinity separates presentation (Pages) from structured content. Pages are strictly for routing and layout. Structured content — News, Blogs, Events, and custom Dynamic Modules — exists independently of the page tree. A Sitefinity page uses widgets to query and display items from Dynamic Modules.

Sitefinity CMS uses a RESTful services API based on the OData protocol, which allows you to create and consume content using standard HTTP operations. Content is organized into built-in modules (News, Blogs, Events, Images, Videos, Documents, Lists) and **dynamic modules** — custom content types you define through the Module Builder.

You create a dynamic module when the built-in Sitefinity CMS modules do not suit your needs. A module must have at least one content type. Dynamic modules support hierarchical content types — a parent-child structure similar to Kentico's page type trees, but defined through a visual builder rather than database schemas.

One detail that matters for ongoing syncs: Sitefinity exposes a **SystemSourceKey** property on every content type — a string property that holds up to 255 characters of ASCII-encoded data. You store an identifier from an external system here and use it to match records during incremental syncs. This is your mapping anchor for delta syncs and prevents duplicate creation on re-runs.

**Sitefinity licensing note:** Sitefinity is a commercially licensed platform with tiered pricing. The Module Builder, multisite support, and certain API capabilities have licensing prerequisites. Before building your migration plan against specific features — particularly dynamic modules and multisite configurations — verify that your Sitefinity license tier includes them. A migration plan built on Module Builder that requires an Enterprise license when you've purchased a lower tier creates a late-stage blocker.

> [!WARNING]
> **Key constraint:** Do not attempt to migrate Kentico Page Types as Sitefinity Pages. Sitefinity Pages do not hold custom schema data — they hold widgets. Migrate your structured data into Dynamic Modules, and let your frontend team build Pages that display those modules.

## How to Extract Data from Kentico

**Direct SQL extraction is the most reliable path for [migrating Kentico content to Sitefinity](https://clonepartner.com/blog/migrate/kentico-to-sitefinity).** Kentico's Site Export Wizard generates a proprietary ZIP package designed for Kentico-to-Kentico transfers. The XML schema inside that ZIP is highly specific to Kentico's internal engine and is useless for cross-platform migrations.

Kentico Xperience 13 provides a REST service at `/rest` (disabled by default) supporting GET/POST/PUT/DELETE for pages and objects. However, the REST API supports limited filtering, no cursor pagination, and no field selection — you must query `/rest/content/currentsite/en-us/all` and parse the nested XML or JSON response, which frequently drops custom fields unless the `classnames` parameter is explicitly specified. For a full content extraction across all page types with custom fields, SQL gives you more control and bypasses response-size limitations entirely.

The core extraction query joins the three tables:

```sql
SELECT 
    t.NodeAliasPath,
    t.NodeGUID,
    t.NodeClassID,
    d.DocumentCulture,
    d.DocumentName,
    d.DocumentPublishFrom,
    d.DocumentPublishTo,
    d.DocumentPageTitle,
    d.DocumentPageDescription,
    d.DocumentModifiedWhen,
    c.*
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.NodeClassID = (
    SELECT ClassID FROM CMS_Class WHERE ClassName = 'Custom.Article'
)
AND d.DocumentCulture = 'en-US'
AND d.DocumentWorkflowStepID IS NOT NULL  -- published only
```

Note the inclusion of `DocumentModifiedWhen` — this column is essential for delta sync runs. Repeat this pattern for each page type, substituting the coupled table name and class name. Query `CMS_Class` where `ClassIsDocumentType = 1` to enumerate all active page types and their coupled table names.

### What to extract beyond page content

- **Media files** — stored in the `Media_File` and `Media_Library` tables (metadata) with physical files on the local filesystem or Azure Blob Storage. Extract file metadata via SQL; download binaries from the `FileGUID`-derived filesystem path or blob URL.
- **Attachments** — `CMS_Attachment` table stores files uploaded directly to pages via the attachments field. These are a separate entity from media libraries and require a separate extraction pass.
- **Categories and tags** — `CMS_Category` table (hierarchical) and taxonomy assignments in `CMS_DocumentCategory`. The category tree must be rebuilt in Sitefinity before content import so that taxonomy GUIDs are available for mapping.
- **Page relationships** — `CMS_Relationship` and `CMS_RelationshipName` tables. Kentico supports both ManyToMany relationships (document-to-document via the relationship name) and structured relationship fields on coupled tables. Each type requires different handling when reconstructed as Sitefinity related data fields.
- **Forms** — `CMS_Form` for form definitions, with form submission data stored in `Form_<formname>` dynamically named tables.

For a deeper walkthrough on Kentico extraction methods and API limits, see [How to Export Data from Kentico](https://clonepartner.com/blog/blog/how-to-export-data-from-kentico-extraction-methods-api-limits-portability).

## How to Map Kentico Content Types to Sitefinity

This is where the migration engineering happens. Kentico page types and Sitefinity content types overlap conceptually but differ in implementation.

| Kentico Concept | Sitefinity Equivalent | Migration Notes |
|---|---|---|
| Page types (CMS.MenuItem, custom types) | Pages + content types or dynamic modules | 1:1 map for simple types; complex types need Module Builder |
| Content-only page types | Dynamic content items | Good fit — both are pure data without presentation |
| Blog posts (CMS.BlogPost) | Blog posts (built-in module) | Fields map closely; blog structure (Blog → Posts) matches |
| News (CMS.News) | News items (built-in module) | Title, Summary, Text fields map directly |
| Events | Events (built-in module) | Date fields may need timezone normalization |
| Media libraries | Image/Video/Document libraries | Binary re-upload required; Sitefinity assigns new IDs |
| Categories (hierarchical) | Hierarchical taxonomies | Rebuild the tree in Sitefinity first; remap GUIDs |
| Tags (flat) | Flat taxonomies (Tags) | Direct mapping but new IDs assigned |
| Custom tables | Dynamic modules or external data | No direct equivalent; evaluate per case |
| Page relationships (ManyToMany) | Related data fields | Requires GUID remapping; import related items before referencing content |
| Page relationships (structured fields) | Related data fields on content type | Define the field in Module Builder before import |

### Fields that don't map

Kentico's **Page Builder widget zones** (MVC) and **editable region content** (Portal Engine) have no direct counterpart in Sitefinity. Kentico stores widget configuration as JSON in the `DocumentPageBuilderWidgets` column of `CMS_Document`. Sitefinity uses its own page editor with a completely different widget system. Similar to [migrating Kentico to Optimizely](https://clonepartner.com/blog/blog/kentico-to-optimizely-migration-a-technical-guide), you must parse the Kentico widget JSON, extract the raw text and assets, and either map them to standard Sitefinity content fields or accept that widget-level page layouts will be rebuilt manually by the frontend team.

Kentico's **workflow versioning** (draft, published, archived states with version history in `CMS_VersionHistory`) does not transfer. You migrate the published version only — identified by records where `DocumentWorkflowStepID` points to a published step. If historical versions are required for compliance or audit purposes, export them separately to a document store outside the CMS.

## How to Import Content into Sitefinity via API

**Sitefinity's OData REST API is the recommended import path.** It supports creating, updating, and deleting all content types — built-in and dynamic — without writing custom .NET code inside the Sitefinity project. Supported content includes news items, blogs, blog posts, events, images, videos, documents, lists, dynamic content, shared content blocks, taxonomies, folders, and pages.

The API is documented at `/api/default/$metadata` on any running Sitefinity instance, which returns the full OData service document describing all available entity types and endpoints. Use this as your ground truth for endpoint names — the exact paths for custom dynamic modules are generated at module creation time.

### Authentication

Sitefinity secures its OData endpoints using OAuth2 via its built-in IdentityServer4 implementation. Your migration script must request a Bearer token before pushing data. The resource owner password grant is the most practical for scripted migration:

```http
POST /Sitefinity/Authenticate/OpenID/connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=password&username={admin_user}&password={admin_pass}
&client_id=sitefinity&client_secret={secret}&scope=openid
```

The returned `access_token` must be included as `Authorization: Bearer {token}` on all subsequent API requests. Tokens expire (default: 1 hour); build token refresh logic into any long-running import script.

### Creating content

Once authenticated, you interact with specific endpoints generated by the Module Builder. A typical content creation request:

```http
POST /api/default/newsitems HTTP/1.1
Content-Type: application/json
Authorization: Bearer {token}

{
  "Title": "Migrated Article Title",
  "Content": "<p>Article body from Kentico</p>",
  "Summary": "Short summary text",
  "PublicationDate": "2026-06-15T00:00:00Z",
  "UrlName": "migrated-article-title",
  "Tags": ["tag-guid-1", "tag-guid-2"],
  "SystemSourceKey": "kentico-node-guid-from-cms-tree"
}
```

Note the `SystemSourceKey` field set to the Kentico `NodeGUID` — this is your idempotency key for delta runs. For dynamic content types, the endpoint follows the pattern `/api/default/{dynamic-type-name}`. Sitefinity auto-generates OData endpoints for every content type, including custom ones built with Module Builder.

### Common API error responses and handling

Knowing what Sitefinity returns when an import fails is as important as knowing the happy path:

| HTTP Status | Cause | Resolution |
|---|---|---|
| `400 Bad Request` | Malformed JSON, invalid field type, or missing required field | Inspect the response body — Sitefinity returns a descriptive error message identifying the field |
| `409 Conflict` | Duplicate `UrlName` within the same content type | Append a suffix (e.g., `-2`) or derive `UrlName` from the `SystemSourceKey` to ensure uniqueness |
| `422 Unprocessable Entity` | Invalid taxonomy GUID reference | Verify the taxonomy item was created and published before referencing it in content |
| `401 Unauthorized` | Expired or missing Bearer token | Implement token refresh; check that the token scope includes write permissions |
| `413 Payload Too Large` | Oversized content body | Split large rich text fields or inline-encoded images; Sitefinity has a default request size limit configurable in IIS |
| `500 Internal Server Error` | ORM constraint violation or cache inconsistency | Check Sitefinity's event log (`/Sitefinity/SF/system/event-log`); usually indicates a schema mismatch or a related item that wasn't published before reference |

Build retry logic with exponential backoff for `500` and `503` responses. Log the `SystemSourceKey` of every failed record so that re-runs can target only failed items.

### The Draft-to-Live workflow

Sitefinity enforces a strict content lifecycle. You cannot POST a record directly to "Live" status. The API requires a specific three-step sequence:

1. **POST** to create a `Draft` item — returns the item's ID and a `Status` of `Draft`.
2. **POST** to `/api/default/{contenttype}({id})/operation/publish` — transitions the item to `Master` (the working published version in the database).
3. The item is now visible on the frontend after the second step, but some Sitefinity configurations with explicit approval workflows require a third publish action through a workflow endpoint.

Failing to follow this sequence results in orphaned records that appear in the database but are invisible on the frontend and do not appear in the content list in Sitefinity's admin. This catches nearly every migration team on the first attempt. Verify your Sitefinity instance's workflow configuration before scripting — a site with custom approval workflows requires additional transition steps that vary by workflow definition.

### OData write throughput and batch processing

Sitefinity's OData services have a default query response limit of 50 items per page on reads. On writes, Sitefinity does not publish a formal rate limit, but practical throughput under default configuration on a standard application server (4 vCPU, 8 GB RAM) is approximately **20–40 content item creates per minute** before response times degrade noticeably. This figure drops when items include large rich text payloads or multiple taxonomy references. Benchmark against your specific environment before committing to a migration window.

To establish your environment's baseline: run a load test posting 10 items per minute, 20, 40, and 80. Measure the 95th-percentile response time. Keep your production import rate below the point where response times exceed 5 seconds — above that threshold, you risk connection pool exhaustion and cascading 500 errors.

OData batch requests (multipart/mixed boundary) let you send multiple POST/PATCH operations in a single HTTP request, reducing per-operation overhead. Use batching for taxonomy assignments and metadata updates; use individual requests for content creation where error isolation matters.

### The C# REST SDK alternative

With the .NET Core Renderer version 14.0, Sitefinity introduced a C# RestSdk that can work with Sitefinity content for both retrieval and creation. If your team is already in .NET, the SDK gives you typed access to Sitefinity's API — useful for complex transformations where raw HTTP calls and JSON serialization become error-prone. The SDK handles token refresh automatically, which eliminates one class of import failure.

## How to Handle Rich Text and Inline Media References

Rich text migration is where most Kentico-to-Sitefinity projects lose time. Kentico's rich text output is HTML — but it is not portable HTML. That HTML frequently contains constructs that Sitefinity cannot interpret and that will break silently on the live site:

- **Kentico K# macros** — syntax like `{% CurrentDocument.DocumentName %}` or `{% CurrentUser.FullName %}` embedded in the HTML. Sitefinity has no equivalent to K# inline rendering. If migrated verbatim, these render as literal broken text. Inventory which macros appear in your content before migration — some may need to be replaced with Sitefinity personalization tokens; others may need to be resolved to static values.
- **Inline image references** using Kentico's `~/getmedia/{guid}/{filename}` and `~/getattachment/{guid}/{filename}` URL patterns.
- **CMSPages file URLs** using the `~/CMSPages/GetFile.aspx?guid={guid}` pattern — a separate format used for document downloads.
- **Internal links** using Kentico's `~/` relative routing or absolute paths tied to the content tree structure.

All of these must be transformed before import:

1. **Strip or replace macros** — Audit K# usage with: `SELECT DocumentContent, DocumentPageBuilderWidgets FROM CMS_Document WHERE DocumentContent LIKE '%{%CurrentDocument%}%'`. Convert dynamic variables to static text or remove them. Where Sitefinity personalization tags are applicable, map them explicitly.
2. **Rewrite media URLs** — Parse the HTML, extract every `~/getmedia/`, `~/getattachment/`, and `~/CMSPages/GetFile.aspx` reference, look up the mapped Sitefinity media ID from your GUID lookup table, and replace with the new Sitefinity URL.
3. **Translate internal links** — Kentico uses tree-based paths; Sitefinity uses `sfref` data attributes for internal links (e.g., `<a href=" [sf_page_node]1234-5678">`). Resolve the Kentico URL, find the corresponding Sitefinity item ID, and rewrite the anchor tag.

A starting-point transformation (expand for production use to cover all URL patterns and add logging for unmatched GUIDs):

```python
import re
import logging

KENTICO_MEDIA_PATTERNS = [
    # getmedia pattern: ~/getmedia/{guid}/{filename}
    (r'~/getmedia/([a-f0-9-]+)/([^"\s?]+)', 'media'),
    # getattachment pattern: ~/getattachment/{guid}/{filename}
    (r'~/getattachment/([a-f0-9-]+)/([^"\s?]+)', 'attachment'),
    # CMSPages GetFile pattern: ~/CMSPages/GetFile.aspx?guid={guid}
    (r'~/CMSPages/GetFile\.aspx\?guid=([a-f0-9-]+)', 'file'),
]

def transform_kentico_media_urls(html, guid_map, source_key=None):
    """
    Replace Kentico media URL patterns with Sitefinity equivalents.
    Logs unmatched GUIDs for manual review.
    guid_map: dict mapping kentico_guid -> sitefinity_url
    source_key: identifier of the content item, for log tracing
    """
    result = html
    for pattern, url_type in KENTICO_MEDIA_PATTERNS:
        def replacer(match, url_type=url_type):
            kentico_guid = match.group(1)
            sf_url = guid_map.get(kentico_guid)
            if sf_url:
                return sf_url
            else:
                logging.warning(
                    f"Unmatched {url_type} GUID {kentico_guid} "
                    f"in content item {source_key}"
                )
                # Return a placeholder rather than a broken URL
                return f'/migration-placeholder/{url_type}/{kentico_guid}'
        result = re.sub(pattern, replacer, result)
    return result
```

This implementation handles three distinct Kentico URL formats, logs every unmatched GUID with its source content item identifier, and inserts a traceable placeholder rather than silently breaking the URL. After migration, query your CMS for placeholder URLs to identify what requires manual resolution.

**Order matters:** Media must be migrated before rich text transformation runs, because you need the Sitefinity media IDs to rewrite inline image references. Any content that references media must be imported after the media GUID lookup table is complete.

## How to Migrate Media Libraries

Moving media files requires a separate, dedicated workflow. Kentico stores media metadata in the `Media_File` table with physical files on the local file system or Azure Blob Storage. Attachments in `CMS_Attachment` are a separate entity with a different storage mechanism. Both must be handled.

The migration sequence:

1. Extract physical files from Kentico's storage provider. For filesystem storage, files are located at `~/CMSFiles/{library-guid}/{filename}`. For Azure Blob Storage, connect using the configured storage account credentials.
2. Map the Kentico folder structure to Sitefinity Document/Image Libraries. Create the target library in Sitefinity via API before uploading files.
3. POST the media metadata (Title, Alt Text, `SystemSourceKey` = Kentico `MediaFileGUID`) to the Sitefinity OData API to create the placeholder media item.
4. Upload the binary file stream to the upload endpoint Sitefinity returns. Sitefinity assigns a new content ID.
5. Publish the media item using the Draft-to-Live workflow — unpublished media items are not accessible from content that references them.
6. Build a **GUID-to-URL lookup table** mapping every Kentico `MediaFileGUID` and `AttachmentGUID` to the corresponding Sitefinity media URL.

This lookup table drives the rich text URL rewriting step and all content-to-media linking. Without it, every inline image and document link in your rich text fields will be broken at import time.

**Sitefinity's permissions model on import:** Media items created via the API default to the owner being the API user (the OAuth account used for the import). If your Sitefinity instance uses library-level permissions, verify that the API user has write access to the target library, and that the resulting media items will be accessible to the roles that need them. Items created with an API admin account may not automatically inherit the correct reader permissions in restricted libraries.

## How to Preserve URLs and SEO

URL structure is the highest-stakes element of any CMS migration. Kentico and Sitefinity generate URLs differently, and the mismatch is inevitable.

Kentico URLs derive from the **NodeAliasPath** in the content tree — for example, `/Products/Widgets/Blue-Widget`. Sitefinity URLs combine page hierarchy with the **UrlName** property of each content item. For built-in types like News, the default pattern is `/news/{url-name}`. A Kentico blog at `/company/news/2024/launch` might become `/news/2024-launch` in Sitefinity.

The migration plan:

1. **Export all Kentico URLs** — query `SELECT NodeAliasPath, DocumentUrlPath, DocumentCulture FROM View_CMS_Tree_Joined WHERE DocumentPublishedVersionExists = 1` for every published page.
2. **Set explicit UrlName values** in Sitefinity during import to match the final path segment from Kentico where possible.
3. **Build redirect rules** for any URLs that cannot be preserved 1:1. Use Sitefinity's built-in redirect module, IIS URL Rewrite rules, or CDN-level redirect rules (preferred for performance at scale).
4. **Migrate meta titles and descriptions** — Kentico stores these in `DocumentPageTitle` and `DocumentPageDescription` columns in `CMS_Document`. Map them to Sitefinity's SEO fields on each content item.
5. **Preserve canonical URLs** and OpenGraph metadata if present. Kentico stores Open Graph data in `DocumentOpenGraphDescription`, `DocumentOpenGraphImage`, and related columns.

> [!TIP]
> **Crawl before you cut.** Run a full site crawl (Screaming Frog, Sitebulb, or similar) on the live Kentico site before migration. Export the URL list, status codes, and redirect chains. Use this as your verification checklist post-migration. Every 200-status URL in the old crawl should either exist at the same path in Sitefinity or 301-redirect to the correct new path. Re-crawl the Sitefinity instance immediately after go-live and diff the two lists.

## How to Handle Multilingual Content

Both platforms support multilingual content, but they store it differently.

Kentico creates **one CMS_Document record per language version**, with the coupled table also storing per-language records linked via `DocumentForeignKeyValue`. The `CMS_Tree` record is shared across all languages, making the Node the language-agnostic anchor.

Sitefinity handles multilingual content through its **culture-aware provider model** — each content item can have multiple language versions. When creating content via the OData API, specify the target culture using the `sf_culture` query parameter:

```http
POST /api/default/newsitems?sf_culture=fr-FR HTTP/1.1
Content-Type: application/json
Authorization: Bearer {token}

{
  "Title": "Titre de l'article migré",
  "Content": "<p>Corps de l'article en français</p>",
  "UrlName": "titre-article-migre",
  "SystemSourceKey": "kentico-node-guid-fr-FR"
}
```

The `sf_culture` parameter must match a culture code configured in Sitefinity's multilingual settings. Posting to a culture not enabled in Sitefinity returns a 400 error.

The migration approach:

1. Extract the **default language** content first and import it into Sitefinity as the primary culture without a `sf_culture` parameter (uses the site default).
2. For each additional language, POST the translation using the `sf_culture` parameter. Reference the same `UrlName` as the primary culture — Sitefinity links translations by `UrlName` within the same content type.
3. **When a translation doesn't exist in Kentico:** decide explicitly whether to create an empty placeholder (preserving the content item in the culture but with blank fields) or skip the culture entirely. Skipping is usually correct — Sitefinity's language fallback setting (configurable per site and per content type) will serve the default culture to users requesting a missing translation. Verify this fallback behavior matches your Kentico configuration before cutting over.
4. Verify that language fallback settings in Sitefinity match your Kentico configuration. In Kentico, fallback behavior is set at the site level via `CMSSiteDefaultEditorCulture`; in Sitefinity, it's configured per site under multilingual settings.

## What You Will Lose in the Migration

Not everything transfers. Be explicit with stakeholders about what doesn't survive:

- **Page templates and layouts** — Kentico's MVC views or Portal Engine templates do not port to Sitefinity. All presentation must be rebuilt.
- **Custom widgets and web parts** — Kentico web parts and MVC widgets have no Sitefinity equivalent. Rebuild as Sitefinity MVC widgets or ASP.NET Core components.
- **Workflow definitions** — Kentico's approval workflows (steps, roles, transition conditions) must be recreated in Sitefinity's workflow system. Workflow state history does not transfer.
- **Online marketing data** — Contact profiles, activities, personas, A/B test results, and email campaign data from Kentico's EMS module do not transfer to Sitefinity.
- **E-commerce data** — If you're using Kentico's built-in e-commerce module, Sitefinity has its own commerce module with a completely different schema. Product catalog, orders, and customer data each require purpose-built transformation.
- **Version history** — Only the published version migrates. Historical versions remain in Kentico's `CMS_VersionHistory` table.
- **User accounts and roles** — Can be migrated but require careful mapping between ASP.NET membership in Kentico and Sitefinity's identity model. Passwords cannot be migrated (different hashing schemes); users must reset passwords on first login.
- **Content staging configurations** — Kentico's content staging (live site synchronization) has no equivalent in Sitefinity's standard configuration. Multisite setups in Sitefinity are configured through site definitions and require license verification.

## Pick the Right Sitefinity Version

Sitefinity 15.4 is the current LTS release with support extending to at least January 2030. Sitefinity CMS requires .NET Framework 4.8 for the backend CMS application, with decoupled rendering available via ASP.NET Core or Next.js using the Sitefinity Renderer or Headless API.

If you're migrating off Kentico and evaluating Sitefinity as the target, aim for **15.4 (LTS) or later**. Sitefinity 14.4 LTS retired April 2027. Don't migrate onto a version that's itself approaching end of support — you'd be re-scoping within two years.

## When to Skip the API and Use Direct SQL Into Sitefinity

Direct SQL insertion into Sitefinity's database is technically possible but dangerous. Sitefinity's OpenAccess ORM maintains internal caches and index structures that SQL bypasses entirely. After a direct SQL insert, the item may not appear in content lists, search indexes, or frontend queries until caches are flushed and the full-text index is rebuilt — operations that require either a Sitefinity restart or execution of Sitefinity's reindex commands through the administration backend.

The specific recovery procedure after a direct SQL insert:
1. Flush the Sitefinity output cache: **Administration > Modules & Services > Output Cache > Clear Cache**.
2. Rebuild the search index: **Administration > Search Indexes > Rebuild All**.
3. Restart the Sitefinity application pool to clear the ORM's in-memory cache.

Even after these steps, there is no guarantee that all ORM relationships will be correctly reconstructed. Use the API unless you have a specific constraint (such as a Sitefinity version too old to support OData writes) and have tested the recovery procedure in a staging environment before running against production.

The API is slower but produces a consistent state. For most migrations, it's the correct choice.

## How Long Does a Kentico to Sitefinity Data Migration Take?

Keep two clocks apart. These figures describe **the data migration effort** — extraction, transformation, API import, validation, and delta sync. They never describe your own replatform, rebuild, or implementation project, which is a separate effort measured in months.

For the data migration itself, most migrations complete within **1–5 business days**, depending on data volume, content complexity, and API write throughput.

By volume:

- **1–500 documents:** 1–2 days.
- **500–5,000 documents:** 3–7 days.
- **5,000+ documents:** A custom engagement, usually an initial bulk migration followed by delta syncs. Larger engagements typically run 7–13+ business days, though actual duration depends on API throughput, data complexity, and field mapping decisions.

Small datasets (under 10,000 records) can complete in under 24 hours with a pre-validated field map and pre-built Sitefinity content types. Full migrations typically run over a weekend with monitoring.

The broader project — rebuilding templates, reimplementing custom functionality, configuring Sitefinity, training editors, UAT, and launch — is a separate effort that your development team or systems integrator owns. That timeline is measured in months.

Given the December 2026 deadline, start scoping at least 3–4 months before your internal cutover date to allow time for field mapping, sample validations, Sitefinity content type creation, and delta sync planning.

## Migration Process: Step by Step

The technical sequence for a Kentico-to-Sitefinity content migration:

1. **Audit the source** — Inventory every Kentico page type, custom table, media library, and form. Query `SELECT ClassName, ClassTableName, ClassIsDocumentType FROM CMS_Class WHERE ClassIsDocumentType = 1` to enumerate all page types with their coupled table names. Document field types, relationships, and content volumes per type.
2. **Map content types** — For each Kentico page type, determine the Sitefinity target: built-in module, dynamic module, or page. Define field-level mappings for every column in each coupled table. Identify fields with no direct equivalent and document how each will be handled.
3. **Build Sitefinity content types** — Create dynamic modules and custom fields in Sitefinity's Module Builder before importing data. Define related data fields and taxonomy assignments. Verify that Module Builder features are included in your Sitefinity license tier.
4. **Create taxonomies** — Import category and tag structures into Sitefinity's flat and hierarchical taxonomies. Publish each taxonomy item. Record the new taxonomy item IDs in the GUID mapping table.
5. **Migrate media** — Upload all images, documents, and video assets to Sitefinity libraries following the five-step sequence above. Build the complete GUID-to-URL lookup table. Publish all media before importing content that references it.
6. **Transform and import content** — Run extraction queries against Kentico SQL, transform rich text HTML (rewriting all media URL patterns, stripping K# macros, rewriting internal links), and POST content to Sitefinity's OData API following the Draft-to-Live workflow. Log `SystemSourceKey` for every created item.
7. **Reconstruct relationships** — After all content items are imported, create related data links using the GUID mapping table to resolve Kentico relationship records to Sitefinity item IDs.
8. **Set up redirects** — Configure URL redirects for any changed paths. Test that all redirects return 301, not 302, and resolve to the correct destination.
9. **Validate** — Record-count parity checks between source and target. Field-level spot checks on a representative sample. Verify media rendering, taxonomy assignments, multilingual content, and relationship links. Check for content items stuck in Draft state.
10. **Delta sync** — For content published in Kentico between the initial bulk migration and cutover, run an incremental sync filtering on `DocumentModifiedWhen > {initial_migration_cutoff_timestamp}`. Use Sitefinity's `SystemSourceKey` property to match existing records and PATCH rather than POST.

## The ClonePartner Approach

ClonePartner specializes in CMS data migrations — extraction, transformation, API import, validation, and delta sync. We operate on a fixed price per project, starting at $500. No hourly billing, no hidden fees, no change orders. Our process includes unlimited sample migrations until the data is correct, and re-migration at no additional cost.

Every project is owned by a dedicated migration engineer. We secure your data with SOC 2 Type II and ISO 27001 (independently audited) safeguards, AES-256 encryption at rest, and TLS 1.2+ in transit. Staging databases auto-purge no later than 30 days after project close.

We handle the data migration. Your development team handles the rebuild.

> Migrating from Kentico to Sitefinity? ClonePartner handles the data migration — extraction, transformation, API import, validation, and delta sync — so your team can focus on rebuilding the frontend. Book a free 30-minute scoping call to get a fixed-price proposal.
>
> [Talk to us](https://clonepartner.com/talk-to-us?duration=30&utm_source=blog&utm_medium=button&utm_campaign=demo_bookings&utm_content=cta_click&utm_term=demo_button_click)

## Frequently asked questions

### Can I migrate from Kentico to Sitefinity automatically?

No. There is no turnkey migration tool between Kentico and Sitefinity. The most reliable approach is extracting content via direct SQL from Kentico's database (CMS_Tree, CMS_Document, and coupled tables) and importing into Sitefinity through its OData REST API or C# REST SDK. Each page type requires its own extraction query and field mapping.

### How long does a Kentico to Sitefinity data migration take?

The data migration itself — extracting, transforming, and loading content — typically completes within 1–5 business days, depending on data volume, complexity, and API rate limits. Small datasets under 10,000 records can finish in under 24 hours. The broader replatforming project (rebuilding templates, custom code, training) is a separate effort measured in months.

### Does Kentico's site export work for migrating to Sitefinity?

No. Kentico's Site Export Wizard generates a proprietary ZIP package containing XML files designed exclusively for Kentico-to-Kentico transfers. This format is not consumable by Sitefinity. For cross-platform migrations, direct SQL extraction gives you structured, portable data.

### What Kentico data cannot be migrated to Sitefinity?

Page templates, MVC views, custom widgets, workflow definitions, online marketing data (contacts, activities, personas), A/B test results, version history, and e-commerce data do not transfer directly. Only published content, media, taxonomies, and metadata can be migrated. Presentation and custom functionality must be rebuilt.

### Can you migrate Kentico widgets directly to Sitefinity?

No. Kentico's widget data is serialized as JSON in the DocumentPageBuilderWidgets column and is tied to Kentico's specific MVC or Portal Engine implementation. Sitefinity uses a completely different widget system. You must extract the underlying structured content and rebuild the presentation layer in Sitefinity.
