Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

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

GraphQL best practices

Boost GraphQL efficiency and security through optimized querying.

GraphQL queries let you request data in a read-only format, letting you specify exactly what information you need. This flexibility helps you optimize performance and ensures efficient data retrieval. You can query each content type in your content management system (CMS), making it easy to access the specific information you require.

Optimizely Graph query structure

Optimizely Graph queries follow a consistent pattern as shown in the following example:

query {
  [ContentType](arguments) {
    items {
      # Fields you want
    }
    total
    facets {
      # Facet information
    }
  }
}

Query techniques

Query for specific types

Query the specific type or interface you need to fetch content for, rather than using generic queries.

# Query specific content type
query GetSpecificArticle($path: String!) {
  ArticlePage(where: { RelativePath: { eq: $path } }) {
    item {
      Name
      TeaserText
      MainBody
      ArticleAuthor
    }
  }
}

Avoid generic queries

Avoid using generic getContentByPath queries with many fragments, as they take a long time to parse. Instead, check which content type a content item belongs to and execute a specific query for that content type.

# Generic query with many fragments – Anti-pattern
query GetContentByPath($path: String!) {
  _Content(where: { RelativePath: { eq: $path } }) {
    items {
      ... on ArticlePage {
        Name
        TeaserText
        MainBody
        ArticleAuthor
      }
      ... on StandardPage {
        Name
        MainBody
        MetaTitle
      }
      ... on ProductPage {
        Name
        ProductDescription
        Price
        ProductImage {
          Url
        }
      }
      # ... fragments for 20+ more content types
    }
  }
}

Use item for single results

Using item instead of items in your queries significantly enhances caching efficiency. When you use items, the cache must account for potential changes across all content, which often leads to frequent cache invalidations. In contrast, item queries permit granular and efficient caching tailored to specific entities, resulting in a substantial improvement in cache hit ratios.

You should use item when fetching content by unique identifiers such as RelativePath, URLs, or code. Opt for item when retrieving a specific piece of content where you expect only one result.

# Better cache performance - use "item" for single results
query GetArticleByPath($path: String!) {
  ArticlePage(where: { RelativePath: { eq: $path } }) {
    item {  # Better caching than "items"
      Name
      TeaserText
      MainBody
    }
  }
}

# Poor cache performance - avoid "items" for single results  
query GetArticleByPathSlow($path: String!) {
  ArticlePage(where: { RelativePath: { eq: $path } }) {
    items {  # Poor caching performance
      Name
      TeaserText
      MainBody
    }
  }
}

Fields and nested fields

Specify what data you want with fields, and nest fields for related content.

query {
  ArticlePage {
    items {
      Name           # Simple field
      PageImage {    # Nested field
        Url
      }
      MainBody       # Rich text field
    }
  }
}

Arguments for filtering and sorting

Use arguments to filter, sort, and paginate data.

query {
  ArticlePage(
    where: { 
      TeaserText: { contains: "Alloy" }
    }
    orderBy: { _modified: DESC }
    limit: 10
  ) {
    items {
      Name
      TeaserText
    }
  }
}

Variables for reusability

Make queries reusable and secure with variables.

query GetArticlesByCategory($category: String!, $limit: Int = 10) {
  ArticlePage(
    where: { 
      MainBody: { contains: $category }
    }
    orderBy: { _modified: DESC }
    limit: $limit
  ) {
    items {
      Name
      RelativePath
      TeaserText
    }
  }
}

Optimization and performance

Query optimization techniques

  1. Request only the needed fields to improve performance.
  2. Use pagination for large result sets.
  3. Batch related queries when possible.
  4. Use fragments to avoid repeating field selections.

Use cached templates for better performance

Cached templates pre-process and cache translated queries as templates, providing substantial performance improvements for repeated query structures. When you execute a query for the first time, it generates a template with placeholders for variables. Subsequent requests that use the same query structure reuse this cached template, eliminating the overhead of repeated query translation. This approach dramatically improves response times, enhancing your overall experience. Enable cached templates in production for optimal performance.

To enable cached templates in your GraphQL requests, you need to add specific parameters. Include the query parameter stored=true and the header cg-stored-query: template.

Supported variable types include Boolean, Date, DateTime, String, Int, Float, Locales, and [Locales]. Unsupported types fall back to Cached Queries.

📘

Note

Float variables support three decimal places of precision (scaled_float with scale of 1000).

Values like 12.34567 are rounded to 12.346.

The following is an example of cached templates:

query GetArticlesByCategory($category: String!, $limit: Int!, $locale: String) {
  ArticlePage(
    where: { TeaserText: { contains: $category } }
    limit: $limit
    locale: $locale
  ) {
    items {
      Name
      TeaserText
      RelativePath
    }
  }
}

Performance best practices

  1. Cache frequently used queries when possible.
  2. Use appropriate indices for filtering.
  3. Monitor query performance and optimize slow queries.
  4. Consider field-level caching for expensive operations.

Security best practices

  • Use variables instead of string concatenation.
  • Validate user input before using it in queries.
  • Implement query complexity limits in production.
  • Use proper authentication for protected content.

System fields overview

Every content item has system fields you can query, providing additional metadata and control over your data retrieval.

query {
  ArticlePage {
    items {
      # Your custom fields
      Name
      TeaserText
      MainBody
      
      # System fields
      ContentLink {
        Id
        GuidValue
      }
      RelativePath
      Language {
        Name
        DisplayName
      }
      _modified
      _fulltext
    }
  }
}