Skip to main content

Outline

At a glance
  • Read vs write separation: IContentLoader handles read operations while IContentRepository governs persistence.
  • Cache discipline: Using the loader ensures content retrieval stays inside the synchronized object cache.
  • Safe mutation pattern: Writable clones prevent accidental modification of cached instances.
  • Lifecycle awareness: Save actions and access levels control versioning, publishing, and security boundaries.

In Optimizely CMS 13, the primary mechanism for interacting with the content tree is a set of modular repository APIs. For developers building high-performance PaaS (DXP) solutions, the distinction between read-only loading and state-changing persistence is not simply a semantic detail. It represents a critical architectural boundary.

Improper use of repository APIs can bypass caches, introduce unnecessary database pressure, or create excessive content versions that degrade synchronization performance with Optimizely Graph. Understanding the difference between loading and persisting content is therefore essential for building scalable solutions.

1. The Core Distinction: IContentLoader vs. IContentRepository

The Optimizely platform assumes that the overwhelming majority of application traffic involves reading content rather than modifying it. To support this architectural reality, repository capabilities are separated into two specialized interfaces.

1.1 IContentLoader: The Read-Optimized Interface

IContentLoader is designed specifically for high-performance content retrieval. It is the primary interface used in front-end rendering pipelines, navigation components, and search result queries.

  • Synchronized object cache: When calling loader.Get<T>(contentLink), the engine first checks the synchronized object instance cache. If the item is already cached, it is returned immediately without a database query.
  • Compile-time guardrails: Because the interface contains no persistence methods, injecting IContentLoader into delivery services guarantees that those services remain read-only.

1.2 IContentRepository: The Persistence Interface

IContentRepository extends IContentLoader and introduces methods that allow developers to modify the content tree. These include operations such as Save, Move, Delete, and Copy.

  • Operational cost: Persistence operations bypass the read cache and trigger validation pipelines, database transactions, and synchronization events.
  • DXP considerations: In cloud deployments, excessive write operations can generate transactional pressure on the Azure SQL database. Bulk operations should therefore be batched or executed through background processing jobs.

2. Content Integrity through Writable Clones

To protect the integrity of the in-memory cache, Optimizely returns content objects as immutable instances. This ensures that multiple concurrent threads can read cached content without risking race conditions or accidental mutation.

The Writable Clone Pattern

Before modifying any content instance retrieved from the repository, you must create a writable clone. This detaches the object from the cache and allows safe in-memory modification before persistence.

public void UpdatePageSubtitle(ContentReference pageLink, string newSubtitle) { // Fetch read-only instance from the repository var readOnlyPage = _contentRepository.Get<StandardPage>(pageLink); // Create writable clone var writablePage = readOnlyPage.CreateWritableClone() as StandardPage; // Modify the cloned instance writablePage.Subtitle = newSubtitle; // Persist the update _contentRepository.Save(writablePage, SaveAction.Publish, AccessLevel.NoAccess); }

3. Managing Persistence with SaveAction

Saving content in CMS 13 interacts with the platform’s versioning system through the IContentVersionRepository. Each save operation can create a new content version depending on the chosen save action.

  • SaveAction.Save (Checkout): Creates a draft version that remains unpublished but available for preview.
  • SaveAction.Publish: Promotes the current draft to the master version and triggers cache invalidation across DXP instances.
  • ForceNewVersion: Creates an additional version even when content data has not changed. This should be used sparingly in automated workflows.

4. Security and Access Control

Repository operations can also enforce the platform’s security model. Depending on how the repository is invoked, operations may either respect user permissions or bypass them for system processes.

  • AccessLevel.NoAccess: Used for background jobs or automated system operations that should bypass editorial permission checks.
  • AccessLevel.Read / Publish: Ensures that the repository validates the current user’s permissions before completing the operation.

Conclusion

Mastering the repository APIs in CMS 13 requires understanding the separation between content retrieval and persistence. By relying on IContentLoader for read operations and applying the writable clone pattern when modifying content, developers maintain thread safety and protect the integrity of the synchronized object cache. Careful selection of save actions and access levels ensures that version histories remain manageable while preserving the stability of the database and the synchronization pipeline that feeds Optimizely Graph.