# What belongs in the CMS vs external systems

### About this export

| Field | Value |
| --- | --- |
| **content_type** | lesson |
| **platform** | contentstack-academy |
| **source_url** | https://www.contentstack.com/academy/courses/integrations-and-the-composable-dxp/what-belongs-in-the-cms-vs-external-systems |
| **course_slug** | integrations-and-the-composable-dxp |
| **lesson_slug** | what-belongs-in-the-cms-vs-external-systems |
| **markdown_file_url** | /academy/md/courses/integrations-and-the-composable-dxp/what-belongs-in-the-cms-vs-external-systems.md |
| **generated_at** | 2026-08-03T11:49:46.889Z |

> Part of **[Integrations and the Composable DXP](https://www.contentstack.com/academy/courses/integrations-and-the-composable-dxp)** on Contentstack Academy. **Academy MD v3** — structured for retrieval; no quiz or assessment keys.

<!-- ai_metadata: {"lesson_id":"02","type":"text","duration_minutes":1,"topics":["What","belongs","the","CMS","external","systems"]} -->

#### Lesson text

# What belongs in the CMS vs external systems

> **TL;DR:**
> 
> *   If content teams create and maintain data through editorial workflows, it belongs in Contentstack; if it is system-generated, transactional, or changes at frequencies editorial workflows cannot match, it belongs elsewhere.
> *   Never store real-time pricing, inventory, user profiles, or session data in the CMS.
> *   Use the “hybrid composition” pattern: your frontend fetches editorial content from Contentstack and transactional data from external APIs, combining them at render time.
> *   Connect systems via a shared identifier (e.g., a shopify\_handle field), not by copying data between them.

Every content platform eventually becomes a dumping ground if nobody draws clear boundaries around what goes in. Contentstack is a system of record for content — editorial text, images, structured data that content teams create and manage. It is not a database for every piece of information your application needs. Drawing the line between what belongs in the CMS and what belongs in external systems is one of the most consequential decisions you make as a developer on a composable architecture, because mistakes here create performance problems, editorial confusion, and integration fragility that compound over time.

## The decision framework

The core question is simple: **who creates and maintains this data?**

If content teams — editors, marketers, documentation writers — create and edit the data through an editorial workflow, it belongs in Contentstack. If the data is system-generated, transactional, computed, or changes at a frequency that editorial workflows cannot accommodate, it belongs in an external system.

This is not a technical distinction about data formats. JSON can represent anything. The distinction is about ownership and lifecycle. Editorial content follows a publish workflow: someone drafts it, someone reviews it, someone approves it, and it gets published to an environment. Transactional data follows a completely different lifecycle: it is generated by systems, updated by automated processes, and consumed in real time.

Here is the framework applied to specific data types:

Data type

Owner

Belongs in Contentstack?

Why

Product descriptions

Marketing team

Yes

Editorial content, reviewed and published

Product prices

Commerce system

No

Changes frequently, governed by business rules, not editorial decisions

Inventory levels

Warehouse/ERP

No

Changes in real time, not editorial

Blog articles

Content team

Yes

Core editorial content

User profiles

Authentication system

No

Transactional, user-generated

Order history

Commerce/ERP

No

Transactional, system-generated

Navigation menus

Content team

Yes

Structural content, editorially managed

Session data

Application server

No

Ephemeral, per-user, real-time

Promotional banners

Marketing team

Yes

Campaign content with publish schedules

Analytics data

Analytics platform

No

System-generated, aggregated

FAQ content

Content team

Yes

Editorial, versioned, localized

Application config

Engineering team

No

Deployment-specific, not editorial

## What belongs in Contentstack

Contentstack excels as the system of record for content that content teams own. This includes:

**Marketing and campaign content:** Landing pages, promotional banners, hero sections, call-to-action text, campaign-specific messaging. This content has a clear editorial lifecycle — it is drafted for a campaign, reviewed, published on a launch date, and often unpublished when the campaign ends. Contentstack's scheduling and release features support this workflow natively.

**Product editorial content:** Product descriptions, feature highlights, comparison tables, sizing guides, care instructions. This is the narrative layer that marketing teams write about products. It follows editorial workflows and benefits from localization, versioning, and approval processes.

**Documentation and knowledge base content:** FAQ entries, help articles, troubleshooting guides, onboarding content. Structured content types with fields for questions, answers, categories, and related articles map cleanly to Contentstack's content modeling capabilities.

**Navigation and structural content:** Header menus, footer links, sidebar navigation, breadcrumb structures. These are editorially managed and change infrequently. Storing them in Contentstack means content teams can update navigation without developer deployments.

**Media and assets:** Images, videos, PDFs, and other files that accompany editorial content. Contentstack's asset management includes a CDN, image transformation API, and folder organization — purpose-built for editorial media.

## What does not belong in Contentstack

Equally important is being explicit about what should not be stored in the CMS:

**Real-time pricing and inventory:** Prices change based on promotions, geographic rules, currency conversion, and dynamic pricing algorithms. Inventory changes with every purchase. Neither of these follows an editorial workflow, and storing them in Contentstack means they are stale the moment an editor publishes them. These belong in a commerce platform like Shopify, commercetools, or your ERP system.

**User accounts and profiles:** User data is transactional and privacy-sensitive. It is created by users, not editors. It is governed by authentication systems, consent policies, and data retention regulations. Contentstack is not an identity provider and should not store personal user data.

**Transaction and order data:** Purchase history, shipping status, payment records, subscription state. These are generated by commerce and billing systems and have their own audit, compliance, and retention requirements.

**Session and state data:** Shopping carts, user preferences, authentication tokens, form progress. This data is ephemeral, per-user, and changes on every interaction. It belongs in session stores, cookies, or client-side state management.

**Application configuration:** Feature flags, A/B test parameters, API endpoints, environment-specific settings. These are deployment concerns managed by engineering, not editorial decisions. Use configuration services like LaunchDarkly, environment variables, or config files.

**Logs and analytics:** Server logs, user behavior data, conversion metrics. These are high-volume, append-only data streams that belong in analytics platforms and data warehouses.

## The hybrid pattern: composition at render time

The real power of a composable architecture is that your frontend combines data from multiple systems at render time. Contentstack provides the editorial layer, and external APIs provide everything else. The frontend is the composition point.

Consider a product detail page for a retail company. The page needs:

*   Product name, description, features, and images (editorial — from Contentstack)
*   Current price and available discounts (transactional — from Shopify Storefront API)
*   Real-time stock availability (transactional — from inventory API)
*   Customer reviews and ratings (user-generated — from reviews platform like Bazaarvoice)

The frontend fetches from all four sources and assembles the complete page:

// Product page: composing data from multiple systems
async function getProductPageData(slug: string) {
  // Editorial content from Contentstack
  const query = stack.contentType("product").entry().query();
  const cmsResult = await query.equalTo("url", \`/products/${slug}\`).find();
  const editorial = cmsResult.entries\[0\];

  // Price and variants from Shopify Storefront API
  const shopifyResponse = await fetch(SHOPIFY\_STOREFRONT\_URL, {
    method: "POST",
    headers: {
      "X-Shopify-Storefront-Access-Token": SHOPIFY\_TOKEN,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: \`{
        productByHandle(handle: "${slug}") {
          variants(first: 10) {
            edges { node { priceV2 { amount currencyCode } availableForSale } }
          }
        }
      }\`,
    }),
  });
  const pricing = await shopifyResponse.json();

  // Inventory from warehouse API
  const inventoryResponse = await fetch(
    \`${INVENTORY\_API}/products/${editorial.sku}/availability\`
  );
  const inventory = await inventoryResponse.json();

  return {
    editorial,   // name, description, images, features from CMS
    pricing,     // current prices from Shopify
    inventory,   // stock levels from warehouse
  };
}

In this pattern, each system is the authoritative source for its own data. The CMS does not try to replicate pricing, and the commerce platform does not try to store rich marketing descriptions. The frontend composes them into a unified experience.

## A retail company example: drawing the boundaries

Consider a mid-size retailer running Contentstack as their CMS, Shopify as their commerce platform, and an ERP system for order management. Here is how they draw the boundaries:

In Contentstack:

*   Product marketing pages (descriptions, lifestyle imagery, feature callouts)
*   Category landing pages (curated collections, seasonal campaigns)
*   Blog articles about product usage and styling
*   Brand story pages
*   Store locator content (store descriptions, hours, directions)
*   Global navigation and footer
*   Promotional banners and announcement bars

In Shopify:

*   Product variants, SKUs, and pricing
*   Inventory levels across warehouses
*   Cart and checkout flow
*   Customer accounts and order history
*   Discount codes and promotion rules
*   Shipping rates and tax calculations

In the ERP:

*   Purchase orders and supplier management
*   Warehouse operations and fulfillment
*   Financial reporting and accounting
*   Returns processing

The connection between systems is the product identifier. Contentstack entries for product content include a shopify\_handle or sku field that links editorial content to the corresponding Shopify product. The frontend uses this identifier to fetch from both systems and compose the page.

{
  "title": "Merino Wool Crew Neck Sweater",
  "url": "/products/merino-crew-neck",
  "shopify\_handle": "merino-wool-crew-neck-sweater",
  "description": "Crafted from 100% Australian merino wool...",
  "features": \[
    { "icon": "temperature", "text": "Temperature regulating" },
    { "icon": "wash", "text": "Machine washable" }
  \],
  "size\_guide": { ... },
  "lifestyle\_images": \[ ... \],
  "care\_instructions": "..."
}

The shopify\_handle field is a simple text field in the content type schema. It does not create a live connection — it is a key that the frontend uses to correlate data from both systems. The editorial team fills it in once, and the frontend handles the runtime composition.

## Common boundary mistakes

> **Common pitfall:** Storing inventory or pricing as CMS fields means the data is stale the moment an editor publishes it — and flash sales or regional pricing cannot be managed without a full editorial review cycle.

### Mistake 1: Storing inventory or pricing in Contentstack

This is the most frequent boundary violation. A team stores product prices as number fields in their Contentstack product content type. It works initially, but problems surface quickly: prices need to change for flash sales without going through content review, regional pricing requires duplicating entries instead of using commerce-native multi-currency support, and inventory counts are stale the moment they are published. The fix is to keep only editorial content in Contentstack and fetch dynamic data from the commerce platform at render time.

### Mistake 2: Using the CMS as a configuration store

Some teams store application settings — API endpoints, feature flags, color theme values, redirect rules — as Contentstack entries. The CMS becomes a key-value store that engineering manages, cluttering the editorial interface with non-content entries. Editors see content types they do not understand and should not touch. Application configuration belongs in environment variables, configuration services, or code.

### Mistake 3: Storing user-generated content in entries

Attempting to write user reviews, comments, or forum posts into Contentstack entries via the Content Management API treats the CMS as a transactional database. The CMA is not designed for high-frequency writes from anonymous users. It has rate limits, requires management tokens (not suitable for client-side calls), and lacks the access control model needed for user-generated content. Use purpose-built platforms for user-generated content and integrate them on the frontend.

#### Key takeaways

- Connect **What belongs in the CMS vs external systems** back to your stack configuration before moving to the next module.
- Capture one concrete artifact (screenshot, Postman call, or code snippet) that proves the step works in your environment.
- Re-read the delivery versus management boundary for anything you changed in the entry model.

## Supplement for indexing

### Content summary

What belongs in the CMS vs external systems. What belongs in the CMS vs external systems TL;DR: If content teams create and maintain data through editorial workflows, it belongs in Contentstack; if it is system-generated, transactional, or changes at frequencies editorial workflows cannot match, it belongs elsewhere. Never store real-time pricing, inventory, user profiles, or session data in the CMS. Use the “hybrid composition” pattern: your frontend fetches editorial content from Contentstack and transactional data from external APIs, combining them at render time. Connect systems via a shared identifier (e.g., a shopify\ handle field), not by copying data between them. Every content platform eventually becomes a dumping ground if no

### Retrieval tags

- What
- belongs
- the
- CMS
- external
- systems
- integrations-and-the-composable-dxp
- lesson 02
- What belongs in the CMS vs external systems
- integrations-and-the-composable-dxp lesson

### Indexing notes

Index this lesson as a primary chunk tagged with lesson_id "02" and topics: [What, belongs, the, CMS, external, systems].
Parent course slug: integrations-and-the-composable-dxp. Use asset_references URLs as thumbnail hints in search results when present.
Never surface LMS quiz content or assessment answers from this file.

### Asset references

_No image or video thumbnail URLs were extracted._

### External links

| Label | URL |
| --- | --- |
| Contentstack Academy home | `https://www.contentstack.com/academy/` |
| Training instance setup | `https://www.contentstack.com/academy/training-instance` |
| Academy playground (GitHub) | `https://github.com/contentstack/contentstack-academy-playground` |
| Contentstack documentation | `https://www.contentstack.com/docs/` |
