---
title: "Hygraph vs Sitefinity: Architecture, TCO, and Migration Guide"
slug: hygraph-vs-sitefinity-architecture-tco-and-migration-guide
date: 2026-08-28
author: Rishabh Makhar
categories: [Migration Guide, General]
excerpt: "Compare Hygraph and Sitefinity across architecture, pricing, content modeling, and migration. A technical guide for teams evaluating headless vs. hybrid CMS."
tldr: "Hygraph is GraphQL-native content infrastructure for composable stacks. Sitefinity is a hybrid .NET CMS/DXP with built-in marketing tools. Your choice depends on tech stack, editorial needs, and where you want complexity to live."
canonical: https://clonepartner.com/blog/hygraph-vs-sitefinity-architecture-tco-and-migration-guide
---

# Hygraph vs Sitefinity: Architecture, TCO, and Migration Guide


# Hygraph vs Sitefinity: Architecture, TCO, and Migration Guide

Hygraph is a GraphQL-native, cloud-only headless CMS built for API-first content delivery. Sitefinity is a .NET-based hybrid platform by Progress Software that can run coupled, decoupled, or fully headless. Choosing between them is not a feature checklist exercise — it is a decision about where you want complexity to live.

Hygraph assumes content is modeled as entities and relationships, delivered through a GraphQL API, and rendered by whatever frontend your team builds. Sitefinity assumes the CMS owns more of the stack: page structure, visual editing, personalization, and rendering coordination. Those are different operating models with different cost profiles, team shapes, and migration paths.

This guide covers architectural differences, real pricing structures, content modeling approaches, localization incompatibilities, and the exact engineering work required to migrate between them — including the rich text transformation that most migration guides skip.

## Architecture: API-First vs. Hybrid Headless

The architectural gap between these two platforms shapes every downstream decision about team structure, frontend ownership, and long-term maintenance.

### Hygraph Architecture

Hygraph (formerly GraphCMS) is a headless CMS built around a GraphQL-native content layer with a distinctive enterprise capability: Content Federation. There is no built-in presentation layer, no page editor, and no server-side rendering engine. It stores structured content and serves it via a single GraphQL endpoint.

**Content Federation** is Hygraph's standout capability. Instead of migrating all enterprise data into the CMS, Hygraph's Content Federation lets you extend your GraphQL schema with external data sources — REST APIs, databases, other CMSes — and query them as a unified graph. The frontend makes one query to Hygraph, and Hygraph resolves the downstream requests. The Growth plan excludes federation entirely; the Enterprise plan supports up to 10 remote sources. Federation queries count against your API operation quota, which matters at scale.

**Infrastructure:** True SaaS. You do not manage servers, databases, or load balancers. You are responsible only for the frontend application and its hosting (Vercel, Netlify, AWS).

**Key constraint:** Hygraph is content infrastructure, not a DXP. Native marketing tooling, analytics, experimentation, visual page building, and personalization capabilities are absent and must be delegated to external systems (Uniform, Builder.io, Ninetailed, or similar).

### Sitefinity Architecture

Sitefinity was originally a traditional .NET CMS but has evolved into an API-first platform that supports three distinct deployment modes simultaneously — a key differentiator from purpose-built headless platforms that force an all-or-nothing architectural commitment:

- **Traditional (Coupled):** Sitefinity manages both content and presentation. Pages are built with drag-and-drop widgets and rendered server-side in ASP.NET Core.
- **Decoupled:** A separate .NET Core Renderer fetches content via APIs while Sitefinity handles the backend. The renderer can also proxy legacy MVC/Web Forms pages during phased modernization.
- **Fully Headless:** Content delivered via OData REST and GraphQL APIs to any frontend, including an official Next.js SDK.

All content types in Sitefinity are exposed via OData services and can be queried, filtered by taxonomies, sorted, and paginated. Those services are automatically generated — no custom code required to expose a new content type. The Sitefinity architecture separates frontend (presentation), backend (content and administration), and data into independent layers, but Sitefinity remains a stateful application requiring session management, distributed caching, and database tuning for high availability.

As of Sitefinity 15.4.8630 (May 2026), the Next.js renderer was updated to Next.js 16 and React 19.2. Customers upgrading from earlier 15.4 versions must apply manual renderer changes — a recurring upgrade cost that should be factored into TCO.

### Architecture Decision Matrix

| Factor | Hygraph | Sitefinity |
|---|---|---|
| **Primary API** | GraphQL (native) | OData REST + GraphQL |
| **Deployment** | Cloud-hosted SaaS only | Self-hosted, Sitefinity Cloud, or hybrid |
| **Page editing** | None (headless only) | WYSIWYG drag-and-drop + headless |
| **Content Federation** | Built-in (up to 10 remote sources, Enterprise only) | Requires custom integration |
| **Personalization** | External tooling required | Native (Sitefinity Insight, licensed separately) |
| **Tech stack dependency** | Stack-agnostic frontends | .NET ecosystem (backend) |
| **Compliance** | SOC 2 Type 2, GDPR, multi-region residency | SOC 2, GDPR, self-hosted option for full control |
| **Locale model** | Field-level variants on a single record | Separate content items per culture/URL |

> [!WARNING]
> **"Both support headless" is not the same as "both are architected the same way."** With Hygraph, the API is the product surface. With Sitefinity, headless sits inside a broader CMS/DXP model that still owns page structure, workflows, and renderer coordination. That difference shows up in team shape, migration scope, and long-term maintenance cost.

## Content Modeling: GraphQL Types vs. Dynamic Modules

How each platform structures content directly impacts migration complexity and developer experience.

**Hygraph** uses a schema-first approach where content types are defined as GraphQL types with strong typing throughout. The schema builder offers 15+ field types with union/polymorphic relations and nested components as first-class GraphQL types. You define models, add fields, and the API is auto-generated with deep querying. Webhooks and UI extensions handle extensibility — if you need custom business logic on publish, a webhook triggers a serverless function (AWS Lambda, Vercel Edge). The CMS stays isolated from your custom code.

**Sitefinity** uses dynamic modules — content types configured through the admin UI or code-first via .NET. Fields map to SQL Server columns. Taxonomies (flat and hierarchical) are a built-in first-class concept. Sitefinity development ties into the Microsoft ecosystem: backend developers write C# to create custom widgets, extend the data model via the Fluent API or Native API, or integrate third-party services through event handlers. Frontend developers build widgets using ASP.NET Core MVC patterns with ViewComponents.

### Field-Type Mapping Reference

This table is the foundation of any Sitefinity-to-Hygraph schema migration. There is no automated tool that handles this translation — it requires deliberate design decisions at each row.

| Sitefinity Field Type | Hygraph Equivalent | Migration Notes |
|---|---|---|
| ShortText | Single Line Text | Direct mapping; check max-length constraints |
| LongText / HTML | Rich Text (AST) | **Requires custom HTML-to-AST parser. Highest complexity.** |
| Choices (flat) | Enumeration | Map option values manually; order may differ |
| Choices (hierarchical) | Model with self-relation | Cannot be represented as a flat enum |
| RelatedData (single) | Reference (one-to-one) | Target model must be migrated first; map IDs |
| RelatedData (multiple) | Reference (one-to-many) | Same dependency ordering applies |
| Media (image) | Asset (image) | Re-upload required; capture new Asset ID for remapping |
| Media (document) | Asset (document) | Same as above |
| Classification / Taxonomy | Enumeration or relational model | See localization section for per-culture complexity |
| Address | Component (nested model) | Hygraph has no native address field; model as component |
| DateTime | Date & Time | Direct mapping; verify timezone handling |
| Number | Int or Float | Choose based on precision requirements |
| Yes/No | Boolean | Direct mapping |
| GeoLocation | Custom (JSON field) | No native geo field; use JSON or String + parse at frontend |

**Note on Choices (hierarchical):** Sitefinity supports nested category trees natively. Hygraph Taxonomies (added 2025–2026) support hierarchical classification, but the data model differs from Sitefinity's relational category approach. Evaluate whether Hygraph Taxonomies meet your requirements before mapping hierarchical Choices to a self-referential model.

> [!WARNING]
> Rich text fields are the most common source of migration pain. Sitefinity stores rich text as HTML with embedded widget references. Hygraph stores rich text as an Abstract Syntax Tree (AST) in a custom JSON format. Every rich text field requires transformation — there is no shortcut, and no off-the-shelf converter handles Sitefinity's embedded widget markup.

## Editorial Experience: Marketers vs. Developers

**Hygraph** is developer-first. Editors fill out structured forms shaped by schema decisions that developers make. There is no concept of a "page" unless you explicitly model a `Page` type with components for SEO, routing, and layout. This makes content highly reusable across web, mobile, and digital displays, but requires editors to think in abstract data structures rather than visual layouts. When content models become complex — nested components, multiple locales, many reference fields — editors frequently report feeling overwhelmed by the interface.

**Sitefinity** excels at visual page building. It ships with in-context editing, a drag-and-drop page builder, built-in A/B testing through Sitefinity Insight, workflow approvals, and API-driven personalization — all without third-party tools. Users frequently highlight its intuitive interface as accessible to non-technical editors.

If your editorial team consists of marketers who need to build pages without developer support, Sitefinity is the stronger choice. If your content is structured data consumed by developer-built frontends, Hygraph's API-first model is cleaner. Replicating Sitefinity's visual, personalized editing experience in Hygraph requires integrating third-party tools (Uniform, Builder.io, or Ninetailed) and significant custom frontend development — costs that belong in your TCO estimate, not your feature comparison.

> [!NOTE]
> Hygraph's reliance on GraphQL means your frontend team needs strong GraphQL expertise. Over-fetching is eliminated, but complex queries with deep relations can hit API complexity limits. Hygraph enforces query complexity scoring internally; queries exceeding the complexity threshold return a 400 error. The specific threshold is not publicly documented but triggers on queries with more than 3–4 levels of nested relations with large result sets. Structure queries to fetch only required fields and use fragments to manage complexity.

## TCO: Where the Cost Actually Lands

TCO is not license alone. The bigger drivers are license shape, infrastructure ownership, frontend responsibility, integration limits, and upgrade surface.

### Platform and License Shape

**Hygraph** publishes hard platform ceilings that directly affect architecture decisions:

- **Hobby (free):** 3 seats, 2 locales, 500K API calls/month (hard-blocked at cap, no overage). Not viable for production.
- **Growth ($199/month):** 10 seats, 10,000 entries, 1M API operations/month, 3 locales, automatic overage billing per block of additional API operations and per GB of asset traffic. Content Federation excluded.
- **Scale ($500/month, where listed):** Higher entry and API limits; check current public pricing as tiers have shifted.
- **Enterprise (custom):** Dedicated support, custom SLAs (up to 99.95% uptime), SSO, multitenancy, 100+ seats, 20+ roles, 60–80+ locales, 50M+ API calls/month, 1M+ content entries, 365-day version retention, up to 10 remote sources (Content Federation), scheduled publishing, audit logs, and dedicated infrastructure.

API call metering applies per environment, aggregated across staging and production. Public usage counters refresh once daily, not in real time — which creates visibility gaps during bulk migrations or traffic spikes. CDN cache hits are excluded from metering; uncached requests are not.

**Sitefinity** uses a different buying model. Pricing is custom and not publicly listed. Deployments are priced per production domain or server for self-hosted, or as a subscription for Sitefinity Cloud. Based on partner and analyst disclosures, mid-market self-hosted licenses typically fall in the $10,000–$50,000+ annual range, though enterprise agreements with multi-site and Insight licensing can exceed this significantly. Sitefinity Insight (analytics, personalization, A/B testing) is licensed separately by contact-profile volume.

**Key overage risk for Hygraph:** High-traffic sites burn through included operations quickly, and Content Federation queries count against the operation limit. Budget for overages from the start if you are on Growth tier.

**Key cost risk for Sitefinity:** No per-API-call metering means more predictable licensing costs, but self-hosted infrastructure (Windows Server, SQL Server, Redis, Elasticsearch on Azure) adds substantial monthly spend that Sitefinity Cloud bakes into the subscription at a premium.

### Infrastructure and Operations

Hygraph pushes the operational surface into the managed platform — you only pay to host your frontend (Vercel, Netlify, AWS S3/CloudFront), which is generally modest relative to CMS infrastructure.

Sitefinity's system requirements for self-hosted deployment center on .NET Framework 4.8 or .NET SDK 10.0 (for the decoupled ASP.NET Core renderer), Windows/IIS, and SQL Server or Azure SQL. Running these components in a high-availability configuration in Azure typically requires multiple VM tiers, managed SQL, Redis Cache, and Elasticsearch or Azure Search — [infrastructure costs typical of a legacy .NET estate](https://clonepartner.com/blog/blog/ektron-vs-coremedia-architecture-tco-migration-guide) that should be line-itemed in any comparison.

### Frontend and Experience-Layer Cost

This is where many evaluations go wrong. Hygraph does not provide a page-building DXP. You own the rendering system, preview behavior, component library, and whatever editor-facing abstractions sit between raw structured content and a publishable page. Higher initial development cost is intrinsic — [as with any headless platform](https://clonepartner.com/blog/blog/duda-vs-kontentai-architecture-tco-migration-guide), you must build the entire presentation layer, routing logic, and preview environments.

Sitefinity productizes more of that surface: built-in templates and widgets reduce initial development cost for standard web projects. The trade-off is that modernization inside Sitefinity still requires manual work. Progress's CLI migration tool handles page and template structure and built-in widgets that have equivalents, but custom widgets need manual reimplementation.

### 3-Year TCO Comparison (Mid-Market Estimate)

| Cost component | Hygraph (Growth → Enterprise) | Sitefinity (Cloud or Self-Hosted) |
|---|---|---|
| **Annual licensing** | $2,400–$50,000+ | $10,000–$50,000+ (estimated; no public list) |
| **Hosting/infrastructure** | Included in SaaS; frontend only (~$1,200–$6,000/yr) | Self-managed infra or Sitefinity Cloud (additional) |
| **Implementation** | Lower infrastructure, higher frontend build cost | Higher infrastructure, lower initial frontend build |
| **Ongoing dev maintenance** | Frontend only; no backend CMS upgrades | Frontend + backend + CMS version upgrades |
| **Overage risk** | High (API call metering, per-GB asset traffic) | Low (no API metering) |
| **Marketing tool add-ons** | External tools required (Uniform, Builder.io: $12,000–$60,000+/yr) | Built-in (Insight, personalization, A/B testing) |
| **Upgrade labor** | Schema migrations; no infrastructure patching | Manual renderer updates per CMS version; DB migrations |

### Migration Complexity by Project Size

| Project size | Content types | Asset volume | Locales | Estimated migration effort |
|---|---|---|---|---|
| Small | < 10 | < 5,000 | 1–2 | 4–8 engineer-weeks |
| Medium | 10–30 | 5,000–50,000 | 2–5 | 10–20 engineer-weeks |
| Large | 30+ | 50,000+ | 5+ | 25–50+ engineer-weeks |

These estimates assume custom scripting, rich text transformation, asset re-upload, and redirect mapping. Each additional locale adds approximately 15–25% to migration effort due to the structural incompatibility between Sitefinity's per-culture content items and Hygraph's field-level locale variants (covered in detail below).

### Upgrade Surface

Sitefinity's phased modernization strength comes with upgrade costs. Sitefinity 15.4.8630 (May 2026) moved the Next.js renderer to Next.js 16 and React 19.2, requiring manual renderer changes for customers upgrading from earlier 15.4 versions. Evaluate your internal capacity to absorb these upgrades annually.

Hygraph's upgrade gotcha is different: when you clone environments, asset URLs change, so any hardcoded asset references in source code or external systems need remediation. These are precisely the costs that rarely appear in first-pass ROI decks.

## Localization: A Structural Incompatibility

This topic receives one sentence in most comparison guides. It deserves its own section because it is a primary driver of migration complexity and post-launch bugs.

### How Each Platform Handles Localization

**Sitefinity** treats localization as separate content items per culture. A news article in English and German exists as two distinct database records with separate URLs (e.g., `/en/news/article-title` and `/de/news/article-title`). Culture variants can have different field values, different publication states, and different workflow stages independently. Taxonomies and related content are also culture-aware, meaning a related item in one language may or may not have a counterpart in another.

**Hygraph** treats localization as field-level variants on a single record. One Article record contains `title` in English, `title` in German, `body` in English, `body` in German — all as variants of the same record, queryable by locale parameter. Non-localized fields (slugs, numeric IDs, boolean flags) are shared across all locales on the same record.

### Localization Migration Mapping Table

| Sitefinity Behavior | Hygraph Equivalent | Migration Implication |
|---|---|---|
| Separate record per culture | Single record, field-level locale variants | N Sitefinity records (one per language) collapse to 1 Hygraph record with N locale variants |
| Separate URL per culture | Locale-prefixed routing in frontend | Frontend must implement locale routing; CMS no longer owns URLs |
| Culture-specific publication state | Locale-level publish state (Hygraph supports this) | Map each culture's status to Hygraph's locale publish state |
| Culture-specific taxonomy assignments | Localized enum labels or localized relational records | Design decision required: localize the label or localize the relationship |
| Related content per culture | Shared references with localized fields on target | References in Hygraph are locale-agnostic; referenced records must carry locale variants |
| Culture-specific media | Shared asset with locale-specific alt text | Alt text can be localized on the Asset record; the file itself is shared |
| Default/fallback culture | Locale fallback configuration in Hygraph | Hygraph supports fallback locale chains; configure explicitly |

**Key implication for migration scripting:** If a Sitefinity site has 10,000 articles in three languages, that is 30,000 Sitefinity records. In Hygraph, that is 10,000 records with three locale variants each. Your migration script must aggregate Sitefinity's culture-specific records by their canonical identifier, then construct a single Hygraph create-mutation with all locale variants populated. Missing this aggregation step results in duplicate records per language.

**URL structure:** Sitefinity generates culture-specific URLs automatically based on site configuration. After migration, your frontend must implement locale routing (e.g., Next.js `i18n` configuration, or manual locale prefix routing). Redirect mapping must account for every culture's URL pattern — not just the default language.

## When to Choose Hygraph

- Your team is JavaScript/TypeScript-native and comfortable with GraphQL
- You need Content Federation across multiple data sources (PIM, e-commerce, custom APIs) — and have Enterprise budget for it
- You are building a composable stack where the CMS is strictly the content layer
- Your editorial team is small or developer-supported
- You want zero infrastructure management and can absorb usage-based cost variability
- You manage content across multiple brands, regions, and data sources from a single schema

## When to Choose Sitefinity

- Your team has .NET expertise and wants to stay in the Microsoft ecosystem
- You need built-in personalization, A/B testing, and analytics without third-party tool licensing costs
- Marketers need to build and edit pages visually without developer involvement
- You need on-premise or private-cloud deployment for compliance or data sovereignty
- You want the flexibility to run headless, decoupled, or traditional rendering — and switch between modes as strategy evolves
- You are modernizing an existing Sitefinity estate incrementally, not executing a full platform exit

## Migrating from Sitefinity to Hygraph

This is the more common direction: teams moving from a monolithic or hybrid .NET CMS to a headless, API-first architecture. The hard part is not exporting records — it is translating one operating model into another. Sitefinity stores page behavior, widget composition, personalization rules, and multisite configuration inside the platform. Hygraph expects you to express all of that through schema, API consumers, and the frontend.

### Step 1: Audit Your Sitefinity Instance

Before writing a single line of migration code, document everything:

- **Content types and dynamic modules** — every custom type, its fields, field types, and relationships
- **Taxonomies** — flat and hierarchical classifications, with culture variants
- **Media assets** — total count, file types, sizes, and all locations where they are referenced (content fields, widget markup, rich text bodies)
- **Page structures** — layouts, widgets, personalization rules, A/B test configurations
- **Custom code** — .NET widgets, custom OData services, event handlers, API customizations
- **Integrations** — Sitefinity Insight, third-party connectors, SSO providers
- **URLs and redirects** — current routing patterns per culture, SEO-critical paths, canonical URLs
- **Locales and cultures** — all active cultures, default culture, fallback chains, content coverage per culture (not all locales are 100% translated)

Separate reusable content from page-only layout. If you scope only "articles, pages, and assets," you will miss localization gaps, widget-embedded content, and personalization data — the expensive part of the migration.

### Step 2: Extract Content from Sitefinity

Sitefinity CMS enables export and import of website content and data structure, with support for the Content Management Interoperability Services (CMIS) open standard.

You have three extraction paths:

1. **OData REST API** — Best for structured content. All content types are exposed automatically. Use `$filter`, `$orderby`, and `$expand` to paginate. For multilingual content, include `?sf_culture=de` query parameters to fetch each culture variant separately.
2. **Direct database access** — Faster for bulk extraction but couples you to Sitefinity's internal schema, which changes between versions and includes complex L2 cache and versioning tables. Use only if the API is too slow for your volume, and only if you have a Sitefinity database schema expert on the team.
3. **CMIS export** — Useful for full site packages, but the format requires additional transformation and does not cleanly separate content from presentation.

```bash
# Fetch English news items from Sitefinity OData API
curl -X GET "https://your-sitefinity.com/api/default/newsitems?$top=100&$skip=0&$orderby=PublicationDate desc&sf_culture=en" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Fetch German variants of the same content type
curl -X GET "https://your-sitefinity.com/api/default/newsitems?$top=100&$skip=0&$orderby=PublicationDate desc&sf_culture=de" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

For each content type, extract all active cultures in separate passes, then aggregate records by their `SystemSourceKey` or canonical ID before constructing Hygraph mutations.

### Step 3: Design the Target Schema in Hygraph

Do not attempt a 1:1 migration of Sitefinity's SQL tables to Hygraph. Design a new, channel-agnostic GraphQL schema. Migrating to Hygraph involves two distinct phases: rebuilding your schema, then importing your content. Hygraph provides the Management SDK and Content API to handle both programmatically, plus a UI-based option for schema creation.

Use the field-type mapping table from the Content Modeling section above as your starting point. Key design decisions:

- Sitefinity **dynamic modules** → Hygraph **models**
- Sitefinity **flat Classifications/Taxonomies** → Hygraph **enumerations** or **Taxonomy models** (new in 2025–2026)
- Sitefinity **hierarchical Taxonomies** → Hygraph **models with self-referential relations** or Hygraph Taxonomy (evaluate fit)
- Sitefinity **RelatedData fields** → Hygraph **reference fields** (one-to-one, one-to-many, or polymorphic)
- Sitefinity **HTML rich text** → Hygraph **Rich Text AST** (requires custom parser; see Step 5)
- Sitefinity **page layouts** → Hygraph **component-based structure** (e.g., a `ModularBlock` union type)
- Sitefinity **image/document fields** → Hygraph **asset fields** (re-upload required; see Step 4)
- Sitefinity **culture-specific records** → Hygraph **localized field variants** on a single record (aggregation required)

Use the Management SDK so schema changes are repeatable and version-controlled. Use `dryRun()` before executing to catch conflicts.

```typescript
import { Client } from '@hygraph/management-sdk';

const client = new Client({
  authToken: process.env.HYGRAPH_PAT,
  endpoint: process.env.HYGRAPH_ENDPOINT,
  name: 'sitefinity-to-hygraph-schema-v1'
});

// Inspect planned changes before committing
const plannedChanges = await client.dryRun();
console.log(JSON.stringify(plannedChanges, null, 2));

// Only execute after review
// await client.run();
```

If you do not normalize the schema — for example, using `String` and `JSON` fields to represent data without transformation — you avoid some upfront complexity but lose the ability to filter, sort, and query those fields through the GraphQL API. Plan to normalize; it pays off in every subsequent API consumer you build.

### Step 4: Migrate Dependencies First, Then Content

Migrate assets and categories first because they have no dependencies. Maintain an ID mapping object for each content type migrated, so you can resolve relationships when importing dependent records.

The dependency ordering is mandatory:

1. **Assets** — Download from Sitefinity's `/api/default/images` and `/api/default/documents` endpoints, upload to Hygraph via the `/upload` endpoint, capture new Asset IDs, and build a `{ sitefinityAssetId: hygraphAssetId }` map
2. **Taxonomies and enumerations**
3. **Independent models** (authors, categories, tags)
4. **Dependent models** (articles, pages — with references resolved via the ID map)
5. **Locale variants** — After creating the base record in the default locale, use `updateArticle` mutations with `localizations` to populate each additional locale variant

```graphql
# Create base record in default locale
mutation CreateArticle($title: String!, $slug: String!, $body: RichTextAST!, $imageId: ID!) {
  createArticle(data: {
    title: $title
    slug: $slug
    body: $body
    coverImage: { connect: { id: $imageId } }
  }) {
    id
  }
}

# Add German locale variant
mutation UpdateArticleLocale($id: ID!, $title: String!, $body: RichTextAST!) {
  updateArticle(
    where: { id: $id }
    data: {
      localizations: {
        upsert: {
          locale: de
          data: { title: $title, body: $body }
        }
      }
    }
  ) {
    id
    localizations { locale title }
  }
}
```

### Step 5: Handle Rich Text Conversion

This is where most migrations stall. Sitefinity stores rich text as HTML strings, often with embedded widget markup. Hygraph expects a structured AST in its custom JSON format.

Plan for this to consume 30–40% of your total migration development time. There is no off-the-shelf tool that handles Sitefinity-to-Hygraph rich text conversion, because Sitefinity's embedded widget markup (`<sf:widget>` tags, inline Sitefinity media references) is proprietary and must be stripped or transformed before conversion.

The conversion requires a two-stage parser:

**Stage 1: Strip Sitefinity-specific markup**
- Remove or transform `<sf:widget>` embedded widget references
- Resolve Sitefinity internal media URLs to external URLs (or defer to post-asset-upload remapping)
- Clean up Sitefinity-generated class names and data attributes that have no meaning in the target system

**Stage 2: Convert clean HTML to Hygraph RichTextAST**

```typescript
import { fromHTML } from 'hast-util-from-html';
import { toMdast } from 'hast-util-to-mdast';

// Hygraph RichTextAST node types
type HygraphNode =
  | { type: 'paragraph'; children: HygraphInlineNode[] }
  | { type: 'heading'; level: 1 | 2 | 3 | 4 | 5 | 6; children: HygraphInlineNode[] }
  | { type: 'bulleted-list'; children: { type: 'list-item'; children: HygraphInlineNode[] }[] }
  | { type: 'numbered-list'; children: { type: 'list-item-child'; children: HygraphInlineNode[] }[] }
  | { type: 'block-quote'; children: HygraphInlineNode[] }
  | { type: 'image'; src: string; altText?: string; width?: number; height?: number }
  | { type: 'table'; children: HygraphNode[] };

type HygraphInlineNode =
  | { type: 'text'; text: string; bold?: boolean; italic?: boolean; underline?: boolean; code?: boolean }
  | { type: 'link'; href: string; children: HygraphInlineNode[] };

type HygraphRichTextAST = { children: HygraphNode[] };

function stripSitefinityWidgets(html: string): string {
  // Remove Sitefinity widget tags and their content
  // Pattern varies by Sitefinity version; audit your specific markup
  return html
    .replace(/<sf:widget[^>]*>[\s\S]*?<\/sf:widget>/gi, '')
    .replace(/<\?.*?\?>/gs, '') // Remove processing instructions
    .trim();
}

function convertHtmlToHygraphAST(html: string): HygraphRichTextAST {
  const cleanHtml = stripSitefinityWidgets(html);
  const hast = fromHTML(cleanHtml, { fragment: true });

  function convertNode(node: any): HygraphNode | HygraphInlineNode | null {
    if (node.type === 'text') {
      return { type: 'text', text: node.value };
    }
    if (node.type !== 'element') return null;

    switch (node.tagName) {
      case 'p':
        return {
          type: 'paragraph',
          children: node.children.flatMap(convertNode).filter(Boolean) as HygraphInlineNode[]
        };
      case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
        return {
          type: 'heading',
          level: parseInt(node.tagName[1]) as 1|2|3|4|5|6,
          children: node.children.flatMap(convertNode).filter(Boolean) as HygraphInlineNode[]
        };
      case 'ul':
        return {
          type: 'bulleted-list',
          children: node.children
            .filter((c: any) => c.tagName === 'li')
            .map((li: any) => ({
              type: 'list-item' as const,
              children: li.children.flatMap(convertNode).filter(Boolean) as HygraphInlineNode[]
            }))
        };
      case 'ol':
        return {
          type: 'numbered-list',
          children: node.children
            .filter((c: any) => c.tagName === 'li')
            .map((li: any) => ({
              type: 'list-item-child' as const,
              children: li.children.flatMap(convertNode).filter(Boolean) as HygraphInlineNode[]
            }))
        };
      case 'blockquote':
        return {
          type: 'block-quote',
          children: node.children.flatMap(convertNode).filter(Boolean) as HygraphInlineNode[]
        };
      case 'strong': case 'b':
        return node.children.flatMap((child: any) => {
          const converted = convertNode(child);
          if (converted && converted.type === 'text') return { ...converted, bold: true };
          return converted;
        }).filter(Boolean)[0];
      case 'em': case 'i':
        return node.children.flatMap((child: any) => {
          const converted = convertNode(child);
          if (converted && converted.type === 'text') return { ...converted, italic: true };
          return converted;
        }).filter(Boolean)[0];
      case 'a':
        return {
          type: 'link',
          href: node.properties?.href || '',
          children: node.children.flatMap(convertNode).filter(Boolean) as HygraphInlineNode[]
        };
      case 'img':
        return {
          type: 'image',
          src: node.properties?.src || '',
          altText: node.properties?.alt || '',
          width: node.properties?.width ? parseInt(node.properties.width) : undefined,
          height: node.properties?.height ? parseInt(node.properties.height) : undefined
        };
      default:
        // Pass through children of unrecognized elements
        return node.children?.flatMap(convertNode).filter(Boolean)[0] || null;
    }
  }

  const children = hast.children
    .flatMap((node: any) => convertNode(node))
    .filter(Boolean) as HygraphNode[];

  return { children };
}

// Usage
const sitefinityHtml = `<p>Article content with <strong>formatting</strong> and <a href="https://clonepartner.com/blog/en/page">links</a>.</p>`;
const hygraphAST = convertHtmlToHygraphAST(sitefinityHtml);
// Pass hygraphAST directly as the value of a RichTextAST field in your mutation
```

**Critical validation step:** After conversion, render the AST in Hygraph's rich text renderer and visually compare output against the original Sitefinity page. Automated field-count validation does not catch rendering differences introduced by structural mismatches.

**Image remapping within rich text:** Images embedded inside Sitefinity rich text (not attached as media fields) must be extracted, re-uploaded to Hygraph as assets, and their `src` values replaced with Hygraph CDN URLs before final import. This requires a two-pass approach: first pass extracts and uploads images; second pass completes the AST conversion with correct URLs.

> [!NOTE]
> Rate limiting applies to Hygraph mutations. Your migration script must implement exponential backoff and batching to avoid HTTP 429 responses during bulk ingestion. Hygraph's public usage counters refresh once daily, not in real time — build your own request counters for observability during bulk loads.

```typescript
async function mutateWithBackoff<T>(
  mutationFn: () => Promise<T>,
  maxRetries = 5
): Promise<T> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await mutationFn();
    } catch (error: any) {
      if (error?.response?.status === 429 && attempt < maxRetries - 1) {
        const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;
        console.log(`Rate limited. Retrying in ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}
```

### Step 6: Validate, Redirect, Launch

- **Content validation:** Compare record counts per content type, per locale. Spot-check 5–10% of records for field accuracy, relationship resolution, and rich text rendering. Automated checks should verify: total record count matches, all referenced assets resolve, all locale variants are populated for multilingual records, no orphaned records with null required fields.
- **URL redirects:** Map every Sitefinity URL to its new equivalent, for every active culture. Sitefinity uses ASP.NET-style routing with culture prefixes; your new frontend will use different patterns. A missed redirect on a high-traffic page can cause [measurable organic traffic loss and a months-long SEO recovery](https://clonepartner.com/blog/blog/wix-to-webflow-migration-a-complete-technical-guide) within days of launch. Use server-side redirects (301), not client-side.
- **SEO preservation:** Plan for SEO from the start. Content delivered through a new frontend requires server-side rendering (SSR) or prerendering (SSG) — client-side-only rendering may not be indexed reliably by all crawlers. Next.js with SSR or ISR is the most common pattern for Hygraph-powered frontends.
- **Asset CDN cutover:** Ensure all asset URLs in content point to Hygraph's CDN, not the old Sitefinity domain. Run a full-text search across migrated content for old domain references before launch.
- **Parallel environments:** Run both systems simultaneously during validation. Content authors should sign off on their content in the new system before the old one goes offline. Define a hard cutover date and communicate a content freeze window.

### Recovery Procedures for Failed Batch Migrations

Hygraph mutations are not transactional — a batch failure at record 4,000 of 6,000 leaves a partial import. Build your migration scripts with these safeguards:

1. **Write a migration log:** Record the Hygraph ID and Sitefinity source ID for every successfully created record. If the run fails, you can resume from where it stopped rather than re-running from the beginning.
2. **Idempotent mutations:** Use Sitefinity's `SystemSourceKey` (or a derived slug) as an external ID. Before creating a record, query Hygraph for an existing record with that identifier. If it exists, skip or update rather than creating a duplicate.
3. **Rollback by deletion:** Hygraph's Content API supports batch deletion. If a migration run produces corrupt or incomplete data, delete records with that migration run's identifier and re-run the affected batch.
4. **Staging environment first:** Run the full migration against a Hygraph staging environment before touching production. Validate completely, then replicate the script against production with a content freeze in place.

### Consider Federation to Reduce Migration Scope

Hygraph Remote Sources can pull external REST or GraphQL data into the Hygraph API at runtime (Enterprise tier required). This is useful when a system of record should stay in place for phase one, reducing the scope of a big-bang migration. It is not a substitute for recreating Sitefinity page composition, workflows, or personalization behavior — but it can defer some data movement and lower the risk of the initial cutover.

## Migrating from Hygraph to Sitefinity

Less common, but it happens — typically when organizations need built-in marketing tools, personalization at scale, or on-premise deployment that Hygraph's cloud-only model cannot satisfy.

Export content from Hygraph using the Content API — the GraphQL API lets you pull every record with its full field set and all locale variants in a single query per type.

```graphql
query ExportArticles($locale: Locale!, $skip: Int!) {
  articles(locales: [$locale, en], first: 100, skip: $skip) {
    id
    title
    slug
    body { raw }
    coverImage { url }
    publishedAt
  }
}
```

The harder part is mapping Hygraph's structured, API-only content into Sitefinity's page-centric model. If your Sitefinity implementation will be headless, the mapping is straightforward. If you are using Sitefinity's page builder, you need to decide how Hygraph content maps to pages, widgets, and content blocks — a design exercise that must precede any data movement.

OData REST services and the C# REST SDK are available for importing data into Sitefinity. To sync data from external systems, use the `SystemSourceKey` property that every Sitefinity content type carries — it is a string field (up to 255 characters) where you can store the Hygraph record ID and use it to identify records during subsequent sync operations or rollback.

**Locale reversal:** Hygraph's single-record, field-level locale model must be exploded back into Sitefinity's per-culture content items. One Hygraph record with three locale variants becomes three Sitefinity records, each posted to the API with the appropriate `sf_culture` parameter. This is the inverse of the aggregation step described in the Sitefinity-to-Hygraph path.

## Common Migration Pitfalls

1. **Underestimating rich text complexity.** This single transformation typically consumes 30–40% of total migration development time. Budget it explicitly.

2. **Ignoring asset dependencies.** Assets must be migrated and verified before any content that references them. Broken asset references are the most common post-migration bug, especially for images embedded in rich text rather than attached as media fields.

3. **Skipping URL redirect mapping per culture.** URL structures change when migrating to a new CMS, and every culture has its own URL pattern. A missed redirect on a high-traffic localized URL means lost organic traffic from that market.

4. **Not accounting for localization structural differences.** Sitefinity's per-culture records and Hygraph's field-level locale variants are not 1:1. Missing the aggregation step creates duplicate records; missing the locale-populate step creates records with empty locale variants that silently fall back to the default language.

5. **Forgetting workflow and permissions.** Content stages (draft, review, published) and role-based access need to be rebuilt in the target platform. Neither platform exports these automatically, and Hygraph's permission model (role → model → field → permission) is more granular than Sitefinity's default setup.

6. **Hardcoded asset URLs after environment cloning.** In Hygraph, cloned environments generate new asset URLs. Catch this in testing — not on launch day.

7. **No idempotency in migration scripts.** A script that cannot resume from a partial failure will force you to re-run the entire migration, potentially creating duplicate records. Build idempotency in from the start.

8. **Treating the migration as a one-time export.** Content authors continue publishing in the source system during migration. Plan for a delta sync of records created or updated after the initial migration run, and define a hard content freeze window before final cutover.

## The Practical Decision

The right answer is not "which CMS has more features." It is "where do we want complexity to live over the next three years?"

If you want content modeled once and consumed everywhere through GraphQL, with your team owning the rendering and experience layer, Hygraph is the cleaner fit. If you want the platform to carry more of the page, editorial, and DXP burden inside a .NET-centered system, Sitefinity is the better fit.

Migrations between these architectural paradigms are high-risk. The work that matters is schema design, locale model translation, relation preservation, asset handling, rich text transformation, and cutover control. Schema design is the migration — the hardest decisions are not about moving data, but about how to restructure your content model to take advantage of the target platform's strengths. Custom scripts with idempotency, exponential backoff, and per-record logging outperform generic migration tools for projects of any significant scale.

> Planning a Hygraph or Sitefinity migration? ClonePartner engineers build custom, automated migration pipelines that handle HTML-to-AST transformations, locale aggregation, asset remapping, and relational data structures. Book a free 30-minute consultation — no commitment required.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### What is the main difference between Hygraph and Sitefinity?

Hygraph is a cloud-only, GraphQL-native headless CMS focused on content infrastructure and Content Federation. Sitefinity is a .NET-based hybrid headless CMS by Progress Software that supports traditional page editing, decoupled, and fully headless modes — with built-in personalization and marketing tools.

### How much does Hygraph cost compared to Sitefinity?

Hygraph starts free (Hobby) with a Growth plan at $199/month and custom Enterprise pricing. Sitefinity uses custom pricing with perpetual or subscription licensing per production domain. Sitefinity typically has higher upfront licensing costs but no per-API-call metering, while Hygraph includes hosting but charges overages on API operations.

### What is the biggest risk in a Sitefinity to Hygraph migration?

Rebuilding page-centric behavior — widgets, layout, forms, personalization, and multisite rules — as structured content plus frontend logic. Exporting records is the easy part. Rich text transformation alone (HTML to Hygraph's AST format) can consume 30–40% of total migration development time.

### Can Sitefinity be used as a headless CMS?

Yes. Sitefinity supports three deployment modes: traditional (coupled with WYSIWYG editing), decoupled (separate .NET Core frontend), and fully headless (content delivered via OData REST and GraphQL APIs). It also has an official Next.js SDK for headless rendering.

### Can Hygraph API limits affect a bulk migration?

Yes. Uncached requests are rate-limited by plan, request sizes are capped, and public usage counters refresh once daily (not in real time). Large imports need batching, exponential backoff, and your own observability to avoid HTTP 429 errors.
