Skip to Content

Introducing Optimizely Feature Flagging

Feature flags for your Optimizely CMS content model

I've just published a new NuGet package: TechnicalDogsbody.Optimizely.FeatureFlagging. It lets you feature flag your Optimizely CMS content properties, so you can change how a property behaves for editors without a code change. You can get it on NuGet or explore the source on GitHub.

The Problem

I built this for features that run across more than one sprint. The code is deployed every sprint and the content model goes with it, so a half-built property or content type shows up for every editor in production before it's ready.

Feature flags are standard practice in application code, but the content model is usually all or nothing. Without them, hiding that work, trying it in one environment first or rolling it back means another code change. With them, you flag the work by environment: on in development and test, off in production until it's finished.

What It Does

You swap the standard attributes on your content types for feature-flagged versions. Each one takes a flag name and the behaviour you want when the flag is on and when it's off. There are attributes for:

  • Display and visibility: rename, move or hide a property with FeatureFlaggedDisplay and FeatureFlaggedScaffoldColumn.
  • Validation: switch rules on and off with FeatureFlaggedRequired or FeatureFlaggedStringLength.
  • Editors and UI: change the editor with FeatureFlaggedClientEditor, or lock a property with FeatureFlaggedEditable.
  • The content model: show or hide a whole content type with FeatureFlaggedContentType, or change culture settings and searchability.

The full list is in the README.

Getting Started

Install the package:

dotnet add package TechnicalDogsbody.Optimizely.FeatureFlagging

Register it alongside the CMS. By default it uses Microsoft Feature Management:

builder.Services.AddCms();
builder.Services.AddFeatureFlaggedContentTypes();

Add your flags to appsettings.json:

{
  "FeatureManagement": {
    "ShowAdvancedOptions": true,
    "BetaValidation": false
  }
}

Then use the attributes on your content types:

[ContentType(DisplayName = "Article Page", GUID = "...")]
public class ArticlePage : PageData
{
    [FeatureFlaggedScaffoldColumn("ShowAdvancedOptions", scaffoldWhenEnabled: true)]
    [Display(Name = "SEO Keywords", GroupName = "SEO")]
    public virtual string SeoKeywords { get; set; }

    [FeatureFlaggedStringLength("BetaValidation",
        enabledMaximumLength: 500,
        disabledMaximumLength: 200)]
    [Display(Name = "Summary")]
    public virtual string Summary { get; set; }
}

Because the flags live in configuration, you can switch them per environment with appsettings.Development.json and appsettings.Production.json.

Bring Your Own Flag Provider

Microsoft Feature Management is the default, but the library only depends on a small interface, so you can use whatever your team already runs:

public interface IFeatureFlagProvider
{
    bool IsEnabled(string featureName);
    IDisposable? OnFlagChanged(Action<string> callback);
}

The README has example providers for LaunchDarkly and Optimizely Feature Experimentation, and it works with Flagsmith, Unleash or a provider of your own. Register yours with AddFeatureFlaggedContentTypes<TProvider>().

Where It Helps

  • Hiding work that spans several sprints until it's finished.
  • Rolling out a new content type or property gradually.
  • Deprecating an old content type while keeping its data.
  • Trying a stricter validation rule before you commit to it.

Things to Know

  • Content type scanning happens once at start-up, so changes to property names, visibility, backing types, culture settings and searchability need an application restart.
  • Content type availability and property editability respond to flag changes at runtime.
  • Change notifications depend on the provider. LaunchDarkly, Optimizely Feature Experimentation and Flagsmith support them, but Microsoft Feature Management doesn't.

You'll need Optimizely CMS 12 or later and .NET 8, 9 or 10. It's MIT licensed, and issues and pull requests are welcome on GitHub.

Andy Blyth

Andy Blyth, an Optimizely MVP (OMVP) and Technical Architect at MSQ DX with a keen interest in martial arts, occasionally ventures into blogging when memory serves.

optimizely-mvp-technology

SaaS CMS Cert

contentful-certified-professional

Andy Blyth