Sitecore Development 101: Optimizing Your Sitecore Serialization

A small change you can make to your Sitecore serialization modules to heavily improve performance by lowering run time

February 28, 2025

By Jeremy Murphy

A Small Change Makes a Huge Difference When It Comes to Optimizing Your Sitecore Serialization

When working with Sitecore serialization, especially in the early stages of a project, performance will often be put on the back burner. However, as the project grows and solutions scale, the time it takes to serialize and deserialize items can increase significantly, creating bottlenecks that slow down your development workflow. While there are many optimizations that can be made at a higher level, sometimes it’s the smallest tweaks that yield the biggest gains.

In this blog, we’ll explore a simple yet impactful change you can make to your Sitecore serialization modules to improve performance. This adjustment requires minimal effort but can have a noticeable effect on your productivity and deployment speed. Let me show you how a little fine-tuning can make a big difference in your serialization process.

The Setup

First let’s paint the picture, let’s say we have a site setup that has a Data folder and inside that Data folder we have 2 child folders, “Articles” and “Config”. Articles is a bucket where the Content Authors will create articles to put on their site and Config is just a folder to hold configuration settings such as rendering options.

When we setup the serialization for this example, since typically you serialize items that are structural or items that won’t be changed by Content Authors, we would want to serialize the parent Data folder, the Article folder but not it’s children and the entire Config folder, item and descendants.

The Simple Approach to Serialization

If you were to actually implement the serialization described above, and had a small project that wouldn’t run you into any performance issues, it would look something like this in your module file:

{
    "namespace": "Content.FakeProject",
    "references": ["Content"],
    "items": {
        "includes": [
            {
                "name": "$Content/Site",
                "path": "/sitecore/content/FakeProject",
                "scope": "ItemAndDescendants",
                "allowedPushOperations": "createAndUpdate",
                "rules": [
                    {
                        "path": "/Data",
                        "scope": "SingleItem",
                        "allowedPushOperations": "CreateOnly"
                    },
                    {
                        "path": "/Data/Articles",
                        "scope": "SingleItem",
                        "allowedPushOperations": "CreateOnly"
                    },
                    {
                        "path": "/Data/Config",
                        "scope": "ItemAndDescendants",
                        "allowedPushOperations": "CreateOnly"
                    },
                    {
                        "path": "/*",
                        "scope": "ignored"
                    }
                ]
            }
        ]
    }
}

With this configuration, serialization will absolutely work and there isn’t anything explicitly wrong with it. It will iterate through the entire FakeProject site creating a single Data item, single Data/Article item and all the Data/Config items. With small datasets, it is a great setup.

The Issue

The issue with this setup is, as datasets increase and more and more items get added, it can easily become a performance issue. Imagine as time goes on, the Authors start adding Articles and before you know it there are 10,000 articles sitting inside buckets organized by year and month. With the above configuration, it has to iterate through all items checking their paths against all the configured rules. Even though we set it up that /Data/Articles should be a single item and all other sub paths ignored, it still has to check those paths to ensure they should be ignored. This results in a serialization that has to check 10,000 articles that could and should be skipped altogether. So how do we configure it to do so?

The Better Approach to Serialization

To set up the serialization module to ensure that we are truly ignoring the Sitecore items we do not want serialized and not bog down the process we would have a configuration module that looks like this:

{
    "namespace": "Content.FakeProject",
    "references": ["Content"],
    "items": {
        "includes": [
            {
        "name": "$Content/FakeProject/Root",
        "path": "/sitecore/content/FakeProject",
        "scope": "SingleItem",
        "allowedPushOperations": "createAndUpdate"
      },
            {
        "name": "$Content/FakeProject/Data",
        "path": "/sitecore/content/FakeProject/Data",
        "scope": "SingleItem",
        "allowedPushOperations": "createAndUpdate"
      },
      {
        "name": "$Content/FakeProject/Data-Articles",
        "path": "/sitecore/content/FakeProject/Data/Articles",
        "scope": "SingleItem",
        "allowedPushOperations": "createAndUpdate"
      },
      {
        "name": "$Content/FakeProject/Data-Config/",
        "path": "/sitecore/content/FakeProject/Data/Config",
        "scope": "ItemAndDescendants",
        "allowedPushOperations": "createAndUpdate"
      }
        ]
    }
}

With this approach, you will notice a minor difference. Instead of having one single include object with the Root project as the path and rules to determine which items to include or ignore, we have it now setup with various includes for the specific items (and possibly their children). This approach is better for 2 reasons.

  1. It solves the initial issue of wasted checks on items we know should be ignored. In this setup, we specify an include for the /Data/Articles path, set it to item only and end the configuration there. We then skip to the /Data/Config include and specify item and descendants. This means it grabs the single item for the Article folder and moved on, it does not check all the children of the Article folder as it did in the last setup.
  2. Each include has its own name, which means when you run the serialization, it puts those items in a folder with that name. This approach, of having multiple includes instead of one include with multiple rules, results in a more organized item structure in your project and makes it easier to find items later if you ever need to reference them or delete them.

This setup can also be further broken down into more includes if sub folders begin to get to large. You could break the config down into a single item config folder and then add includes for sub folders of the config path if any of those became item dense.

A Small but Noticeable Change

The upside and downside of the Sitecore Serialization modules is that it is fully customizable to your needs, but you can quickly configure yourself into a runtime nightmare if you are not careful. With this better approach to your configuration setup you are now headed in the right direction to have a more efficiently organized and scalable serialization process.

Thanks for reading! If you found this helpful, you can also check out my other blogs in the Sitecore Development 101 series:

Sitecore Development 101: Creating a Custom Rendering Contents Resolver

Sitecore Development 101: Creating an Interactive PowerShell Script

Sitecore Development 101: The Ultimate Beginner’s Sitecore PowerShell Cheat Sheet 

 

Picture of Fishtank employee Jeremy Murphy

Jeremy Murphy

Sitecore Developer

Jeremy Murphy is a self-driven full-stack developer with over six years of software development experience. He has been Sitecore certified for several years and also has certifications in Web Accessibility. He is fluent in front-end frameworks such as React and in developing scalable custom web APIs that deliver on customer experience. Outside of work, he is passionate about health and fitness and spends a lot of his time outdoors, either camping in the Maritimes or travelling the world.