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

A technical guide to migrating content from Kentico to Umbraco — covering EAV schema translation, SQL extraction, field mapping, import APIs, and the gaps you must plan for.

Roopendra Talekar Roopendra Talekar · · 23 min read
Kentico to Umbraco 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 Umbraco Migration: A Technical Guide

Moving content from Kentico to Umbraco is a cross-platform migration between two .NET CMS systems that share no common data format, no shared migration tool, and fundamentally different content storage models. Both run on C# and SQL Server, but their underlying data architectures are incompatible — you are not moving rows from one database to another. You are translating Kentico's flat, relational page types into Umbraco's Entity-Attribute-Value (EAV) model, and converting Kentico's widget-based Page Builder data into Umbraco's proprietary Block JSON.

The data migration — extracting structured content from Kentico's relational tables and writing it into Umbraco's document type system — is a solvable engineering problem. The broader replatform (rebuilding templates, redesigning the front end, re-implementing custom logic) is a separate project your development team owns, measured in months. This guide covers the data side: how Kentico stores content, how Umbraco expects to receive it, and the field-level mapping decisions you'll face.

Info

TL;DR: There is no native export tool for moving from Kentico to Umbraco. The Kentico Migration Tool only supports upgrades to Xperience by Kentico. Cross-platform migrations require direct SQL extraction from Kentico's CMS_Tree and CMS_Document tables, transforming the payload, and injecting it into Umbraco via the IContentService (C#) or the Management API (Umbraco 14+).

Why teams are moving from Kentico to Umbraco in 2026

Two structural pressures are pushing Kentico shops toward Umbraco.

Kentico Xperience 13 end of support. KX13 enters full end-of-life on December 31, 2026. As of January 2026, it is already in security-only support — no functional bug fixes, no new features. After December 2026, Kentico provides no hotfixes, security patches, or technical support of any kind. Your site will still run, but it becomes fully unsupported software running on an unpatched stack. For teams that don't want to adopt Xperience by Kentico (XbyK) — a substantially different product that requires a full rebuild regardless — Umbraco is the most common .NET-based alternative.

Licensing and cost structure. Xperience by Kentico self-managed licensing starts at approximately $990/month; SaaS plans start at approximately $1,990/month (figures from Kentico's published pricing as of 2025). Umbraco CMS is open-source under the MIT license with no core license fee — costs are hosting, optionally Umbraco Cloud for managed infrastructure, and optionally Umbraco Commerce. For organizations that used Kentico primarily as a content management system and found the DXP bundle (marketing automation, A/B testing, contact management) overbuilt for their needs, the TCO difference is significant. Teams that depend on Kentico's marketing automation features will need to replace them with third-party tools regardless of which CMS they move to.

For more on the KX13 deadline, see Kentico Xperience 13 End of Support 2026: What Actually Changes.

How Kentico stores content (and why extraction is harder than it looks)

Kentico's content model is split across three interconnected database layers per content item. Understanding this structure is the prerequisite for planning extraction — getting it wrong produces pages with system fields but no custom content.

  • CMS_Tree — one row per page regardless of language. Stores tree position (NodeAliasPath, NodeParentID), the page type reference (NodeClassID), the site reference (NodeSiteID), and non-versioned metadata.
  • CMS_Document — one row per language version per page. Stores versioned properties, Page Builder widget data (in the DocumentPageBuilderWidgets column), and the foreign key (DocumentForeignKeyValue) that links to the coupled data table.
  • Coupled data tables (CONTENT_<PageType>) — one table per page type containing the custom fields you defined. A "Blog Post" page type gets a CONTENT_BlogPost table with dedicated columns like BlogPostTitle, BlogPostBody.

The View_CMS_Tree_Joined view joins CMS_Tree and CMS_Document for convenience, but it does not include coupled data columns. To extract a complete page record, you must join all three layers yourself. This is the most common extraction mistake: engineers query the view and end up with records that have no custom field values.

A standard extraction query:

SELECT 
    t.NodeAliasPath,
    t.NodeName,
    t.NodeClassID,
    t.NodeSiteID,
    d.DocumentName,
    d.DocumentCulture,
    d.DocumentPageTitle,
    d.DocumentPageDescription,
    c.* -- Custom fields from the specific page type
FROM CMS_Tree t
INNER JOIN CMS_Document d ON t.NodeID = d.DocumentNodeID
INNER JOIN CONTENT_BlogPost c ON d.DocumentForeignKeyValue = c.BlogPostID
WHERE t.NodeSiteID = @SiteID  -- Critical for multisite Kentico instances
ORDER BY t.NodeLevel, t.NodeOrder;

Note on multisite Kentico installations: Kentico frequently runs multiple websites within a single database instance, each identified by NodeSiteID. Every extraction query must filter by NodeSiteID — omitting it produces a merged dataset across all sites. If you're migrating one site out of a multisite install, identify the correct NodeSiteID from CMS_Site before writing any extraction queries.

Media storage adds another layer. Files can live in CMS_Attachment (database-stored attachments), in a media library on the filesystem (~/<sitename>/media/), or in Azure Blob Storage. Each requires a different extraction approach. Media metadata lives in Media_Library and Media_File tables; physical files are separate from the database records that reference them.

Portal Engine vs. MVC origin matters for template rebuild scope. Kentico sites built on the older Portal Engine architecture (Web Parts, page templates stored in CMS_PageTemplate) require a substantially different rebuild than sites built on the Kentico MVC pattern. Portal Engine sites have no reusable Razor views — every template is a database-driven Web Part composition. MVC Kentico sites have actual .cshtml files that can be adapted with less effort. Before planning your replatform, determine which architecture your source site uses: check CMS_PageTemplate for non-empty PageTemplateLayout values (Portal Engine) versus the presence of a dedicated MVC project with view files (MVC pattern). This determination affects the template rebuild timeline by months, not days.

Kentico's Site Export Wizard generates a proprietary ZIP file designed only for Kentico-to-Kentico transfers — it is useless for cross-platform migrations.

For a full breakdown of every extraction method, see How to Export Data from Kentico: Extraction Methods, API Limits & Portability.

Warning

Kentico's REST API does not support pagination for pages. The offset and maxrecords parameters only work for object data, not page data. If you plan to extract via the REST API, you'll receive all matching pages in a single response — which can fail or timeout on large content trees. This is documented behavior in the Kentico REST API reference. Direct SQL extraction is the more reliable path for migration-scale data pulls.

How Umbraco stores content (and how to get data in)

Umbraco's content model uses an Entity-Attribute-Value (EAV) pattern — a data model where properties are stored as rows in a central table rather than columns in a dedicated table. This is the primary friction point in any Kentico-to-Umbraco migration.

Where Kentico's CONTENT_BlogPost table has dedicated columns for Title, Author, and Body, Umbraco fragments the same Blog Post across multiple tables:

  • umbracoNode — stores the item's position in the content tree.
  • umbracoContentVersion — tracks draft/published state and version history.
  • cmsPropertyType — defines the field schema (property aliases, data types).
  • umbracoPropertyData — stores the actual values as strings, integers, or JSON blobs depending on the property editor type.

Because of this EAV structure, you cannot write directly to Umbraco's SQL database during a migration. Direct inserts bypass Umbraco's NuCache (the XML-based in-memory content cache that powers the front end), break the backoffice UI, and corrupt the content tree. Umbraco will not rebuild NuCache automatically from raw SQL inserts; you will end up with content in the database that doesn't appear on the front end or in the backoffice. All data must flow through Umbraco's application-layer APIs — no exceptions for bulk imports.

Three import paths exist:

Method Umbraco Versions Use Case Notes
IContentService (C#) All modern versions (v7+) Programmatic content creation via server-side code Most reliable for bulk migration. Runs inside the Umbraco application context. Manages NuCache automatically.
Management API (REST) v14+ (client credentials from v15+) External system-to-system content creation Full CRUD. Uses OAuth 2.0 Client Credentials flow. Self-documented via Swagger at /umbraco/swagger.
uSync v7+ XML serialization import Designed for Umbraco-to-Umbraco schema transfers, not cross-platform migration.

Why uSync is not a data loader: uSync is the industry standard for moving Umbraco schema (Document Types, Data Types) and content between Umbraco environments. It serializes content to XML files using Umbraco's own internal representations. It is not designed for ingesting data from external platforms. While you could theoretically generate uSync-compatible XML files from Kentico data, generating valid uSync XML that matches Umbraco's internal structure — including correct UDI formats, property type aliases, and culture variant structures — is significantly harder and more brittle than calling IContentService directly. Use uSync for what it's built for: schema synchronization between Umbraco environments.

For more on Umbraco's data portability, see How to Export Data from Umbraco: Methods, API Limits & Portability.

Which Umbraco version should you target?

Target Umbraco 13 (LTS) or Umbraco 17 (LTS) for new migrations starting in 2026 — but with an important constraint.

Umbraco 13 (LTS) is supported until December 14, 2026, and remains the more widely adopted version as of mid-2026. Umbraco 17 (LTS), released November 2025 and running on .NET 10 LTS, is supported until November 27, 2028. It includes the full Management API with client credentials support, backoffice load balancing, and the latest Block Grid property editor architecture. If you're starting a migration now and your go-live date is late 2026 or beyond, targeting Umbraco 17 avoids an immediate upgrade obligation.

Avoid Umbraco 13 for net-new migrations if your timeline extends past December 2026 — you would be migrating to a version entering end-of-life almost immediately. Umbraco 18 (STS, released June 2026) is available but carries only 12 months of support, making it a poor migration target.

Which version affects your import approach: Umbraco 13 and below require IContentService for programmatic imports. Umbraco 14+ adds the Management API, and Umbraco 15+ adds client credentials OAuth flow for external callers. If you're building a migration pipeline in a language other than C#, or want to run migration tooling outside the Umbraco application process, you need Umbraco 15+ for a clean external API approach.

Content model mapping: Kentico page types → Umbraco document types

A Kentico page type maps to an Umbraco document type, but the mapping is rarely one-to-one at the field level. This is where most of the migration design work happens.

Page type → document type mapping

Kentico Concept Umbraco Equivalent Migration Notes
Page type Document type Each Kentico page type becomes one or more Umbraco document types.
Coupled data fields Document type properties Map each Kentico field to the appropriate Umbraco property editor. Data type conversions are required for dates, files, and relationships.
Content tree (NodeAliasPath) Content tree Both use hierarchical trees. Umbraco's tree hierarchy is reflected in URLs by default — plan your tree structure before importing.
Language versions (CMS_Document per culture) Variants Each Kentico culture version maps to an Umbraco language variant. The Umbraco document type must have language variants enabled, and each variant must be set before saving.
Page Builder widgets (DocumentPageBuilderWidgets) Block Grid / Block List No direct mapping. Kentico's Page Builder JSON must be parsed widget-by-widget and rebuilt as Umbraco Block data structures with valid UDIs.
Categories (CMS_Category) Tags or custom taxonomy No direct equivalent. Map to Umbraco's Tags property editor or build a custom taxonomy using content nodes.
Attachments (CMS_Attachment) Media items Extract binary data from the database, upload to Umbraco's media section via IMediaService, update all references.
Media library files Media section Download from filesystem or Azure Blob, re-upload to Umbraco Media via IMediaService. File-copy to ~/media/ without API calls is not recognized by Umbraco.
Custom tables No direct equivalent Decide whether to migrate as Umbraco content, external database tables, or drop them. No migration path exists within Umbraco's content system.
Forms (Kentico Forms) Umbraco Forms Umbraco Forms is a paid add-on (pricing available at umbraco.com). Form definitions must be recreated manually; submitted data can be migrated via scripts.
Smart Search (Kentico) Examine / Elasticsearch Kentico Smart Search indexes are not portable. Examine (Lucene-based, built into Umbraco) replaces Smart Search for most use cases. Custom search implementations using Elasticsearch require separate configuration.
Staging module (Kentico) Umbraco Deploy / uSync Kentico's staging module synchronizes content and objects between environments. Umbraco Deploy (commercial) or uSync (open-source) covers schema sync; content sync between environments requires additional tooling.
Approval workflows Umbraco content workflow Kentico's workflow engine with multi-stage approval and document-level ACLs does not transfer. Rebuild using Umbraco's built-in content review workflow or commercial packages like Plumber.
Macros (Portal Engine) Partial views / Surface Controllers Kentico macros are a Portal Engine concept with no Umbraco equivalent. Each macro must be re-evaluated and rebuilt as an Umbraco partial view or a Surface Controller action. This is template code, not data.

Field-level data type mapping

Kentico Field Type Umbraco Property Editor Conversion Notes
Text field (200/500 char) Textstring Direct string copy.
Long text / HTML Rich Text Editor (TinyMCE) HTML content transfers, but inline media references (~/getmedia/ and /getattachment/) must be rewritten to Umbraco media UDIs. Rewriting is not optional — broken references will render as dead image links.
Integer / Decimal Numeric Direct value copy. Verify decimal precision matches Umbraco's Numeric editor configuration.
Date/time Date Picker Kentico stores as SQL datetime; Umbraco's Management API and IContentService both accept ISO 8601 strings. Convert before import.
Boolean True/False (Toggle) Direct mapping.
File / Attachment Media Picker Upload to Umbraco Media first via IMediaService, then reference the resulting UDI (e.g., umb://media/12345...). Never store raw file paths.
Page relationship (linked pages) Content Picker / Multi-Node Tree Picker Kentico uses NodeGUID references. Kentico GUIDs are not preserved in Umbraco. Maintain a lookup table mapping Kentico NodeGUID → new Umbraco content GUID during migration; resolve all references after content import completes.
Drop-down / Selector Dropdown or Radio Button List Static option lists must be recreated as Umbraco data type prevalues before content import. Content import will fail if the data type doesn't exist yet.
Repeater fields (Portal Engine) Block List / Nested Content Repeaters have no direct Umbraco equivalent. Each repeater usage must be redesigned as a Block List with a corresponding element type. This is design work, not just data mapping.

Step-by-step: the data migration process

1. Audit and inventory Kentico content

Query CMS_Class to enumerate all page types. For each, count rows in the coupled data table and note field definitions. Identify media libraries, attachments, custom tables, form data, and multisite boundaries. This inventory determines migration scope.

-- Count pages per page type in Kentico, filtered by site
SELECT 
    c.ClassName, 
    c.ClassDisplayName, 
    COUNT(t.NodeID) AS PageCount,
    s.SiteName
FROM CMS_Tree t
INNER JOIN CMS_Class c ON t.NodeClassID = c.ClassID
INNER JOIN CMS_Site s ON t.NodeSiteID = s.SiteID
WHERE t.NodeSiteID = @SiteID
GROUP BY c.ClassName, c.ClassDisplayName, s.SiteName
ORDER BY PageCount DESC;
 
-- Identify Portal Engine vs. MVC page types
SELECT ClassName, ClassDisplayName, ClassIsDocumentType,
    CASE WHEN ClassInheritsFromClassID IS NOT NULL THEN 'MVC-likely' ELSE 'Portal-likely' END AS TemplatePattern
FROM CMS_Class
WHERE ClassIsDocumentType = 1;

Also inventory language cultures from CMS_Document:

SELECT DocumentCulture, COUNT(*) AS DocumentCount
FROM CMS_Document d
INNER JOIN CMS_Tree t ON d.DocumentNodeID = t.NodeID
WHERE t.NodeSiteID = @SiteID
GROUP BY DocumentCulture;

2. Design the Umbraco document type schema

Create document types in Umbraco that represent your target content model. This is not necessarily a 1:1 copy of the Kentico schema — it's an opportunity to simplify and consolidate. Use Umbraco compositions (shared mixin document types) to group repeated property sets like SEO fields, hero images, or page metadata across multiple document types rather than duplicating them. Enable language variants on any document type that must support multilingual content before you import any variant data.

Create all document types, data types, and media types before importing any content. The import will fail if it references a document type alias or property type alias that doesn't exist.

3. Extract content from Kentico

Direct SQL against the Kentico database is the most reliable extraction method. Join CMS_Tree and CMS_Document with each coupled data table per page type and export to JSON. Extract media files separately from the filesystem, Azure Blob, or CMS_Attachment table.

Prefer JSON over CSV as the intermediate format. CSV loses data types, mangles multi-line HTML fields, and cannot represent nested structures. JSON preserves type information, nesting, and null values, and maps directly to the object graphs your transformation code will produce.

For multilingual sites: extract each DocumentCulture as a separate record keyed by NodeID + culture code. You will need all language variants for a node available simultaneously when creating the Umbraco content node with variants.

4. Transform and map data

The transformation layer is where the bulk of migration engineering effort concentrates. Key transformations required:

  • Rewrite inline media URLs from Kentico's /getmedia/{guid}/{filename} and /getattachment/{guid}/{filename} patterns to Umbraco media references. This must be done programmatically using a GUID-to-UDI lookup table built during media import — not a regex guess.
  • Remap content GUIDs — Kentico NodeGUID and DocumentGUID values are not preserved in Umbraco. Build a lookup table mapping each Kentico NodeGUID to its new Umbraco content node GUID. Resolve cross-content references after all content nodes exist.
  • Transform rich text HTML to match Umbraco's TinyMCE expectations — remove Kentico-specific markup, rewrite media paths, and remove Portal Engine control syntax if present.
  • Map categories to Umbraco tag values or build taxonomy content nodes first.
  • Convert dates from SQL datetime to ISO 8601 strings.
  • Rebuild drop-down values against Umbraco data type prevalues (which must already exist in the target).

Mapping Kentico widgets to Umbraco blocks

If your Kentico site uses the Page Builder (KX13), structured page content isn't stored in standard text fields — it's stored in the DocumentPageBuilderWidgets column as JSON. This JSON encodes widget types, widget zones, widget properties, and layout metadata specific to Kentico's Page Builder schema. It cannot be moved into Umbraco without transformation.

Modern Umbraco (v13+) uses the Block Grid Editor or Block List Editor for page layouts. These editors store content as nested JSON objects with Umbraco-specific unique identifiers (UDIs), content type references, and layout configurations. A representative Umbraco Block List JSON structure:

{
  "layout": {
    "Umbraco.BlockList": [
      {
        "contentUdi": "umb://element/1a2b3c4d5e6f7g8h9i0j"
      }
    ]
  },
  "contentData": [
    {
      "contentTypeKey": "heroBannerElementTypeKey",
      "udi": "umb://element/1a2b3c4d5e6f7g8h9i0j",
      "headline": "Extracted from Kentico widget",
      "backgroundImage": "umb://media/0987654321abcdef"
    }
  ],
  "settingsData": []
}

Each Kentico widget type requires a corresponding Umbraco element type (a document type flagged as an element type), and the transformer must generate syntactically valid UDIs for each block instance. If the transformer produces invalid UDIs, mismatches the contentTypeKey, or omits required properties, Umbraco will silently drop the block or crash the backoffice page editor for that content node. There is no automated conversion utility — each widget-to-block mapping is custom code.

Kentico Page Builder zones (which organize widgets into columns and sections) must also be translated into Block Grid area configurations. Block Grid is more expressive than Block List and better represents zone-based layouts, but it requires defining grid column configurations at the document type level before import.

5. Migrate media files

Import media before content — content nodes reference media by Umbraco UDI, which only exists after the media node is created. Attempting content import before media import produces unresolvable references.

Extracting from Kentico:

-- Extract media library file metadata
SELECT 
    ml.LibraryName,
    ml.LibraryFolder,
    mf.FileGUID,
    mf.FileName,
    mf.FileExtension,
    mf.FilePath,
    mf.FileSize,
    mf.FileMimeType
FROM Media_File mf
INNER JOIN Media_Library ml ON mf.FileLibraryID = ml.LibraryID
WHERE ml.LibrarySiteID = @SiteID;
 
-- Extract page attachments stored in database
SELECT 
    a.AttachmentGUID,
    a.AttachmentName,
    a.AttachmentExtension,
    a.AttachmentBinary, -- binary content if stored in DB
    a.AttachmentUrl
FROM CMS_Attachment a
INNER JOIN CMS_Document d ON a.AttachmentDocumentID = d.DocumentID
INNER JOIN CMS_Tree t ON d.DocumentNodeID = t.NodeID
WHERE t.NodeSiteID = @SiteID;

Importing to Umbraco via IMediaService:

// Correct Umbraco media import — never copy files directly to ~/media/
var mediaItem = _mediaService.CreateMedia(fileName, parentFolderKey, "Image");
using var fileStream = File.OpenRead(localFilePath);
mediaItem.SetValue(_mediaFileManager, _mediaUrlGeneratorCollection, 
    _shortStringHelper, _contentTypeBaseServiceProvider, 
    "umbracoFile", fileName, fileStream);
_mediaService.Save(mediaItem);
 
// Capture the UDI for the cross-reference lookup table
var newUdi = mediaItem.GetUdi().ToString(); // "umb://media/12345..."
guidLookup[kenticoFileGuid] = newUdi;

You cannot copy files into the ~/media/ folder and expect Umbraco to recognize them. Umbraco's media system stores file path metadata in the database; without the database record created by IMediaService, the file is invisible to the CMS.

Info

Inline media references are the most common source of broken content after migration. Every /getmedia/ and /getattachment/ URL embedded in rich text fields must be rewritten to the corresponding Umbraco media UDI or a resolved public URL. A regex-based find-and-replace is the minimum viable approach; a proper approach builds a GUID-to-UDI lookup table during media import and rewrites all references programmatically in the transformation step. For more on this problem, see How to Migrate Images, Attachments & Embeds Without Broken Links.

6. Import content into Umbraco

For a high-volume import, two primary paths exist.

Option 1: IContentService (C# — Umbraco 13 and below, works in all versions)

// Simplified Umbraco content import via IContentService
var content = _contentService.Create("Page Title", parentId, "blogPostAlias");
 
// Set simple properties
content.SetValue("bodyText", transformedHtml);
content.SetValue("author", "Extracted Author");
content.SetValue("publishDate", DateTime.Parse(kenticoDate).ToString("yyyy-MM-ddTHH:mm:ss"));
 
// Set culture-specific properties for multilingual content
content.SetCultureName("Page Title", "en-US");
content.SetValue("bodyText", transformedHtmlEnUs, "en-US");
content.SetCultureName("Titulní strana", "cs-CZ");
content.SetValue("bodyText", transformedHtmlCsCz, "cs-CZ");
 
// Save draft, then publish
_contentService.Save(content);
_contentService.Publish(content, new[] { "en-US", "cs-CZ" });

Performance constraints for IContentService: Each SaveAndPublish call interacts with the EAV schema, fires internal event handlers, updates NuCache, and triggers Examine indexing. On a standard server with default settings, throughput is approximately 10–30 content nodes per minute for simple page types, dropping to 3–10 nodes per minute for complex pages with Block Grid data or many properties. For a 10,000-page migration, expect 6–17 hours under default settings.

To improve throughput:

  • Disable Examine indexing during the migration run: call ExamineManager.Instance.IndexProviders to suspend indexers, then rebuild the index after import completes.
  • Batch saves: accumulate multiple IContent objects and use _contentService.Save(IEnumerable<IContent>) rather than saving one at a time.
  • Run during off-peak hours to avoid contention with the live site.

Option 2: Management API (Umbraco 14+ for content, 15+ for client credentials)

The Management API accepts JSON payloads and is self-documented at /umbraco/swagger. It allows orchestrating migration from external tooling (Python, Node.js, a dedicated integration platform) without compiling custom C# into the Umbraco solution. The client credentials OAuth flow (Umbraco 15+) enables machine-to-machine authentication without interactive login.

Constraints: the API is subject to standard HTTP rate limiting and network latency. Payloads with large Block Grid structures or binary-encoded content can hit size limits. Batch imports to 50–100 nodes per request depending on payload size. The Swagger documentation at /umbraco/swagger is authoritative for request/response schema.

For multilingual content: set all culture variants on a node before the first save call. Adding variants to an already-saved node requires a separate PATCH operation per culture.

7. Validate and reconcile

Validation is not optional — it is how you confirm every record arrived before decommissioning the source system.

  • Record count parity: compare COUNT(*) per page type in Kentico against document count per document type alias in Umbraco.
  • Field-level spot checks: randomly sample 50–100 pages across page types and compare field values between source and target manually or via automated diff.
  • Media reference validation: crawl all published Umbraco URLs and check for 404s on image and file references.
  • Internal link validation: verify that content-to-content links (Content Picker values, Multi-Node Tree Picker values) resolve to existing nodes.
  • Language variant completeness: for each multilingual page type, verify that all expected culture variants exist and are published.
  • Block Grid rendering: open each page type that uses Block Grid in the Umbraco backoffice and confirm that blocks render correctly in the editor — broken Block JSON will crash the editor for that node.

URL structure and SEO preservation

URL changes are the highest-impact SEO risk in any CMS migration.

How Kentico generates URLs: Kentico derives the default URL from NodeAliasPath, with optional custom URL patterns configured per page type (stored in DocumentUrlPath and site URL settings). Custom domain-to-site mappings are in CMS_SiteDomainAlias.

How Umbraco generates URLs: Umbraco builds URLs from the content tree hierarchy by default. A content node at /root/blog/my-post in the Umbraco tree produces the URL /blog/my-post. If the Umbraco tree structure differs from the Kentico NodeAliasPath structure, URLs will change.

Pre-migration URL mapping process:

  1. Extract all published Kentico URLs by querying CMS_Tree with NodeAliasPath and DocumentUrlPath for any custom overrides.
  2. Simulate the Umbraco URL output for your planned tree structure.
  3. Diff the two URL sets to identify every URL that will change.
  4. For every changed URL, implement a 301 redirect.

Redirect implementation options in Umbraco:

  • umbracoRedirectUrl table: built-in redirect tracking, managed in the backoffice. Suitable for moderate volumes.
  • IIS URL Rewrite rules (web.config): better for large-scale redirect maps (10,000+ URLs), processed at the server level before Umbraco handles the request.
  • Skybrud.Redirects package: provides a CSV-import-capable redirect management UI within Umbraco.

Preserve <title> tags, meta descriptions, canonical URLs, and Open Graph metadata as migrated fields in your Umbraco document types. Do not rely on manual re-entry — map these fields explicitly in your extraction and transformation steps.

Search: Kentico Smart Search → Umbraco Examine

Kentico's Smart Search uses Lucene-based indexes configured via CMS_SearchIndex and bound to specific page types and fields. These indexes are not portable — their configuration is specific to Kentico's application layer.

Umbraco uses Examine (a Lucene.NET wrapper) as its built-in search framework. Examine indexes are configured in code via IUmbracoIndexConfig implementations. When content is imported via IContentService, Examine will index it automatically (unless you've disabled Examine during the migration run, in which case you must rebuild indexes after import).

For teams using external search (Azure Cognitive Search, Elasticsearch, Algolia), the Kentico connector configuration does not transfer. You will need to implement an Umbraco-compatible connector using the target search platform's SDK.

What doesn't migrate

The data migration moves structured content. These items require separate handling by your development team and cannot be automated:

  • Templates and views — Kentico MVC views must be rebuilt as Umbraco Razor views. Portal Engine templates (Web Parts) have no Umbraco equivalent and must be designed from scratch. Template rebuild scope is the primary driver of development timeline.
  • Macros (Portal Engine) — Kentico macros are a Portal Engine-specific concept. Each must be re-evaluated and rebuilt as Umbraco partial views, Surface Controller actions, or Umbraco block element types.
  • Page Builder widget implementations — the widget code (C# controllers and Razor views) must be rebuilt as Umbraco block element types with corresponding controllers. Only the content data inside widgets can be migrated; the rendering code cannot.
  • Custom code and integrations — scheduled tasks, custom event handlers (DocumentEvents, WorkflowEvents), integration bus configurations, and custom API endpoints must be reimplemented against Umbraco's equivalents (INotificationHandler, Umbraco's built-in scheduler, etc.).
  • User accounts and passwords — Kentico password hashes use Kentico's own hashing implementation and are not compatible with Umbraco's ASP.NET Identity system. Plan for a forced password reset flow for all editor accounts. Frontend member accounts require the same treatment.
  • Workflow and approval configurations — Kentico's workflow engine with multi-step approval, document-level permissions, and workflow history does not transfer. Rebuild using Umbraco's content workflow or a package like Plumber. Permission structures must be rebuilt from scratch in Umbraco's user groups system.
  • Kentico marketing features — email marketing, contact management, A/B testing, personas, and marketing automation have no Umbraco equivalents. These require third-party tools (HubSpot, Mailchimp, Optimizely, etc.) regardless of which CMS you move to.

Common failure modes

Across migrations of Kentico installations at varying scales, the same failure patterns repeat:

  • Broken inline media — the single most common post-migration defect. Kentico's /getmedia/ and /getattachment/ URLs embedded in rich text don't resolve in Umbraco. Every instance must be rewritten programmatically using a GUID-to-UDI lookup table.
  • Missing coupled data — extracting from View_CMS_Tree_Joined without joining the coupled data table produces content nodes with only system fields and no custom field values. Affects 100% of content of that page type.
  • Page Builder data loss — moving Kentico Page Builder widget JSON into Umbraco Block Grid without a proper per-widget transformer produces corrupt or empty blocks. Umbraco silently drops invalid blocks rather than throwing errors.
  • GUIDs assumed stable — Kentico NodeGUID values are not preserved in Umbraco. Content-to-content references that relied on Kentico GUIDs must be remapped using a lookup table built during migration.
  • Language variant misalignment — if the Umbraco document type isn't configured for language variants before import, only one culture's content imports. Adding variant support after the fact requires reimporting all variant data.
  • No multisite filter — extracting without WHERE NodeSiteID = @SiteID in a multisite Kentico installation produces a merged dataset across all sites, leading to duplicate content and incorrect tree structure.
  • Media imported after content — importing content before media means all media references resolve to non-existent UDIs. References don't auto-heal when media is added later; they must be rewritten again.
  • Examine memory exhaustion — running a large import with Examine indexing enabled causes Lucene to attempt incremental index updates for every saved node. On imports exceeding ~2,000 nodes, this commonly causes OutOfMemoryException. Disable Examine before bulk import; rebuild after.

When Kentico to Umbraco is the wrong move

Use this checklist to evaluate fit. More than two "yes" answers in a category indicates Umbraco may not be the right target.

Reconsider Umbraco if your organization depends on:

  • Kentico's built-in e-commerce module with complex pricing rules, promotions, and order management (Umbraco Commerce is a separate product with different capabilities — evaluate independently before committing)
  • Kentico email marketing, contact scoring, or marketing automation (no Umbraco equivalent; requires third-party replacement regardless)
  • Kentico A/B testing or personalization features (no direct Umbraco equivalent)
  • Tight integration between content authoring and CRM/marketing workflows that rely on Kentico's contact management layer

Consider a headless platform instead of Umbraco if:

  • You're moving away from server-rendered templates entirely and building a React/Next.js/Vue frontend
  • Your primary use case is structured content delivery via API rather than web page authoring
  • Your editorial team doesn't need a structured backoffice for page composition

Purpose-built headless platforms (Contentful, Sanity, Strapi) may be better fits than adapting Umbraco's hybrid headless capabilities for fully API-first architectures. Umbraco's Content Delivery API (available from v12+, documented at docs.umbraco.com) is a viable headless option for teams that want to keep Umbraco but serve content to decoupled frontends.

Cutover strategy

A "big bang" migration — exporting everything on Friday and hoping it imports cleanly by Monday — is a reliable path to data loss and rollback. The structured approach:

  1. Schema freeze — lock Kentico page types. No new fields or page type changes during the migration window. Schema changes after extraction invalidate your mapping configuration.
  2. Target readiness — Umbraco document types, data types, Block element types, and media folder structure must be fully deployed and validated before any content import begins.
  3. Sample migration — move a representative subset (100–200 pages across all page types, plus associated media) to validate field mapping, Block JSON generation, media reference rewriting, and URL structure. Fix issues before running at full scale.
  4. Bulk migration — move the historical content payload while Kentico remains live and editors continue working. This is the largest time investment.
  5. Delta sync — on launch weekend, identify all content created or modified in Kentico since the bulk migration timestamp (filter by DocumentModifiedWhen > @BulkMigrationTimestamp) and re-import only the changed records.
  6. Validation — record count parity checks per page type, field-level spot checks, media reference crawl, and internal link verification before DNS cutover.
  7. DNS cutover and redirect activation — switch DNS, activate redirect rules, and monitor 404 logs for the first 48–72 hours.

How long does a Kentico to Umbraco data migration take?

Keep two timelines separate: the data migration and the site rebuild.

Site rebuild timeline: configuring Umbraco document types, designing templates, writing frontend code, and rebuilding custom integrations takes months and is the primary cost driver of any replatform. This is work your development team or Umbraco implementation partner scopes independently.

Data migration timeline is driven by record volume, schema complexity, media library size, and the presence of Page Builder widget data requiring transformation. Reference benchmarks:

Migration Profile Approximate Timeline
Under 1,000 content nodes, minimal media, no Page Builder 1–2 business days
1,000–10,000 nodes, moderate media library, simple field types 2–5 business days
10,000–50,000 nodes, large media library, some widget transformation 5–10 business days
50,000+ nodes, heavy media, complex Block Grid mapping, multilingual 10–20+ business days, typically structured as bulk migration + delta syncs

These timelines assume schema design is complete and the target Umbraco environment is ready to receive content. Schema design and field mapping decisions can add 1–3 days for complex content models.

Start scoping at least 3–4 months before your internal go-live deadline or the KX13 end-of-support date (December 31, 2026) to allow time for sample validation, bulk migration, and delta syncs without compressing the cutover window.

Frequently Asked Questions

Is there an automated tool to migrate from Kentico to Umbraco?
No. There is no official migration tool or shared data format between Kentico and Umbraco. The Kentico Migration Tool (KMT) only supports upgrades to Xperience by Kentico. Migration requires extracting data from Kentico's SQL database (CMS_Tree, CMS_Document, and coupled data tables), transforming it, and importing via Umbraco's IContentService (C#) or Management API (v14+).
How long does a Kentico to Umbraco data migration take?
The data migration itself — moving content records between systems — typically takes 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. This is separate from the broader replatform (rebuilding templates and custom functionality), which takes months and is work your development team owns.
What Umbraco version should I migrate to from Kentico in 2026?
Target Umbraco 17 (LTS), released November 2025 and supported until November 2028. It runs on .NET 10 LTS and includes the full Management API with client credentials. Avoid Umbraco 13, which reaches end-of-life December 14, 2026 — migrating to it would create an immediate upgrade obligation.
Do Kentico page types map directly to Umbraco document types?
Conceptually yes — each Kentico page type maps to one or more Umbraco document types. But field-level mapping requires careful planning. Kentico stores custom fields as database columns in coupled data tables, while Umbraco uses property editors with an EAV model. Data type conversions, inline media URL rewrites, and GUID remapping are all required.
What content doesn't transfer in a Kentico to Umbraco migration?
Templates, Page Builder widget configurations, custom code, URL routing rules, user passwords, workflow definitions, and document-level permissions do not transfer as data. They must be rebuilt in Umbraco by your development team. Inline media references (Kentico's /getmedia/ URLs) embedded in rich text also need rewriting.

More from our Blog