Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Control field indexing

Understand how Optimizely Graph counts fields against the 100,000 field limit and control indexing per property to keep query and synchronize performance healthy.

Optimizely Graph has a hard limit of 100,000 fields. Every property you sync to Graph adds one or more fields to the schema. Graph maintains each field on every content update. As you approach the limit, syncing and queries slow down. Control indexing at the property level to stay within the limit and keep publishing and queries fast.

Why field count matters

Every property on every content type that you sync to Optimizely Graph creates one or more fields in the Graph schema. Graph updates every indexed field each time the content changes. A higher field count means more work per sync and higher latency when you publish.

The 100,000-field limit can seem relevant only to large accounts with hundreds of content types. In practice, field count grows faster than the number of content types and properties suggests.

How Graph counts fields

The number of fields Graph creates is not the same as the number of properties on your content types. Depending on how Graph indexes a property, it maps that property to more than one field in the schema:

  • An output-only property uses the fewest fields.
  • A queryable property uses more.
  • A searchable property uses the most.

Because queryable and searchable properties each use more than one field, your field count grows faster than your property count. Reducing indexing on properties you do not filter or search is the most direct way to keep the count down.

Control indexes at the property level

Not every property needs filter or search indexes. Some properties you only read in a GraphQL query. You never filter them with a where clause or use them for full-text search. For those, Graph does not need a filter or search index. Mark such a property as output-only. Its value still returns in queries but uses fewer fields against your limit.

📘

Note

Output-only properties still return their values in query responses. Graph removes only the filter and search indexes.

The .NET integration provides two ways to control indexing: the [GraphProperty] attribute and the conventions API. Both are part of the Optimizely.ContentGraph.Cms.NetCore package.

Use the [GraphProperty] attribute

Add the [GraphProperty] attribute to a C# property and pass a PropertyIndexingMode. The enum has two values:

  • PropertyIndexingMode.Default – Stored and filterable, but not full-text searchable.
  • PropertyIndexingMode.OutputOnly – Stored and returned in query results only. Graph does not build a filter or search index for it.
[ContentType(DisplayName = "Article Page", GUID = "...")]
public class ArticlePage : PageData
{
    // Default: stored and filterable, but not full-text searchable
    [GraphProperty(PropertyIndexingMode.Default)]
    public virtual string Author { get; set; }

    // OutputOnly: returned in query results only, not filterable or searchable.
    // This reduces the field-count and indexing impact of the property.
    [GraphProperty(PropertyIndexingMode.OutputOnly)]
    public virtual string InternalNotes { get; set; }
}

OutputOnly reduces overhead without losing access to the data. Graph still returns the value when you query for it. Because Graph does not index it for filtering or search, it costs far less of your indexing and query budget. Use OutputOnly for every property you do not filter or search on.

📘

Note

[GraphProperty] only reduces indexing. The attribute has no Searchable mode. To make a property full-text searchable, mark it searchable through the standard CMS property setting. Graph then indexes it for search unless a [GraphProperty] mode of Default or OutputOnly overrides the setting.

Use the conventions API

The conventions API configures indexing without attributes, using the singleton ConventionRepository. Call ForInstancesOf<T>() and then Set(...) per field with an IndexingType:

  • IndexingType.OnlyStored – Stored and returned only, not queryable or searchable. Equivalent to PropertyIndexingMode.OutputOnly.
  • IndexingType.Queryable – Filterable and queryable. Equivalent to PropertyIndexingMode.Default.
  • IndexingType.Searchable – Full-text searchable. Supported only for primitive types, string, and DateTime.
conventionRepository.ForInstancesOf<ArticlePage>()
    .Set(x => x.MainBody, IndexingType.Searchable)      // full-text searchable
    .Set(x => x.Author, IndexingType.Queryable)         // filterable, queryable
    .Set(x => x.InternalNotes, IndexingType.OnlyStored) // returned only
    .ExcludeField(x => x.AdminNotes);                   // dropped from the schema entirely

To remove a property from the Graph schema completely, use ExcludeField. Graph neither stores nor returns an excluded field.

Optimizely CMS (SaaS)

In CMS (SaaS), set the indexing type per property through the CMS UI or the REST API rather than in code. For details, see Content types (SaaS).

If you have already reached the limit

If your Graph account has reached 100,000 fields and Graph is rejecting additional content types or properties, recover in two steps.

Reduce indexed fields where possible

Work through your content types and reduce indexing on every property you do not filter or search. Set each one to OutputOnly or OnlyStored, or use ExcludeField to drop it from the schema entirely.

Run a smooth rebuild

Changing indexing settings does not remove existing over-indexed fields from your Graph account. To apply the updated schema and remove the fields you no longer need, run a smooth rebuild.

A smooth rebuild follows a blue-green deployment model. Graph creates a fresh green slot alongside your live blue slot. It re-syncs your content into the green slot with the updated indexing settings and builds a clean schema from scratch. Query the green slot with the cg-query-new: true HTTP header to verify it before you promote it. When you are satisfied, click Accept to promote the green slot to live. If something is wrong, click Abandon.

❗️

Warning

Until you accept or abandon the rebuild, Graph syncs content only to the green slot, not to the live slot. Content updates are not visible on the live site during this window. Schedule the rebuild for a low-traffic period, and avoid publishing content you need live until you accept or abandon it.

For the full process, see Smooth rebuild.