<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by Jon Williams</title> <link>https://world.optimizely.com/blogs/jon-williams/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>Optimizely Graph Best Practices - Security, Access Control and Performance Optimisation</title>            <link>https://world.optimizely.com/blogs/jon-williams/dates/2026/1/optimizely-graph-best-practices---security-access-control-and-performance-optimisation/</link>            <description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Building on &lt;a title=&quot;Optimizely Graph Best Practices - Content Modelling and Querying&quot; href=&quot;/link/b5461a25051a4305b9dac43dc3adbeb7.aspx&quot;&gt;Part 1&#39;s content modeling and querying practices&lt;/a&gt;, this Part 2 focuses on the security and performance considerations essential for running Optimizely Graph in production environments.&lt;/p&gt;
&lt;p&gt;We&#39;ll explore authentication strategies - from Single Key for public content to HMAC with role-based access control for restricted scenarios - and discuss when a Backend for Frontend (BFF) layer provides crucial security benefits. You&#39;ll also learn performance optimisation techniques including cached templates, query fragments, and approaches to eliminate inefficient query patterns.&lt;/p&gt;
&lt;p&gt;These operational practices ensure your Graph implementation delivers content securely and efficiently at scale. In the final post of this series, we&#39;ll cover API key management, integration strategies, and governance approaches for long-term maintainability.&lt;/p&gt;
&lt;h2&gt;1. Security &amp;amp; Access Control&lt;/h2&gt;
&lt;h3&gt;Do&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;:&lt;/span&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;1. Use role-based API keys&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;If your content is publicly available then you can use the &#39;Single key&#39; mechanism for authenticating and reading content from Graph.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;This key can be accessed from the PaaS Portal:&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;&lt;img src=&quot;/link/aa9c3bea8c9240ad83d78dc99fa3fd40.aspx&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Note that &#39;Single key&#39; access only returns content that is accessible to the the&amp;nbsp;&lt;strong&gt;Everyone &lt;/strong&gt;group within the Content Management System. &lt;/span&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;It is good for general website content, as it is read-only, fast and can be called directly from a frontend (headless) application.&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;2. Respect CMS content permissions&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;If you need to access restricted content (i.e. content that is not accessible by the&amp;nbsp;&lt;strong&gt;Everyone&lt;/strong&gt; group) then you&#39;ll need to do this using &#39;role-based access control&#39; (RBAC) and preferably through HMAC.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;HMAC access uses the &#39;App key&#39; and &#39;Secret&#39; (available from the PaaS Portal) and can be combined with `cg-username` and `cg-roles` request headers to only fetch content where one of the roles or the username specified has read access.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;However, given that this mechanism requires the &#39;App key&#39; and &#39;Secret&#39;, which could be used to provide full access to all Graph resources without restriction, it important that these are not used from frontend code. If these are needed then a Backend for Frontend (BFF) layer is recommended to securely proxy requests to Graph while keeping credentials server-side.&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;3. Avoid exposing draft or non-public content&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Using the &#39;Single key&#39; authentication mechanism only gives access to published, non-expired content that is available to everyone. &lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;However, if using the &#39;App key&#39; and &#39;Secret&#39; to authenticate then it is possible to include additional headers (`cg-include-deleted`, `cg-include-hard-deleted` and `cg-include-expired`) to also include deleted and expired content. If you are using these (or user / role based access) for any reason then proceed with care, as there may be out-of-date or potentially sensitive content being exposed.&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;4. Be aware that GraphiQL is openly available&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Be aware that anyone with your Single key can access the GraphiQL interface at&amp;nbsp;&lt;code class=&quot;bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]&quot;&gt;https://cg.optimizely.com/app/graphiql?auth={singlekey}&lt;/code&gt;, which exposes your full content schema through introspection.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;&lt;img src=&quot;/link/e30ac56b6787472eb556c14af0393dee.aspx&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;If you choose to expose the Single key in client-side code (as is common for a headless website) then at least be aware that this is a possibility and potentially increases the attack vector on your estate.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;If you elect to implement a BFF then this can be used to proxy requests to Optimizely Graph, allowing the Single key to be hidden, as well as adding functionality like caching, rate limiting, transformation and more sophisticated authentication.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;2.&amp;nbsp;&lt;/span&gt;Performance Optimisation&lt;/h2&gt;
&lt;h3&gt;Do&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;:&lt;/span&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;1. Use cached templates and cached queries&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;This is one of the biggest performance gains to be made when querying Optimizely Graph!&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;Rather than &#39;hardcoding&#39; queries, such as this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;query GetArticlesByCategory {
  ArticlePage(
    where: { TeaserText: { contains: &quot;Technology&quot; } }
    limit: 10
    locale: &quot;en&quot;
  ) {
    items {
      Name
      TeaserText
      RelativePath
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;... Using a query containing GraphQL variables, such as the following, enables Optimizely Graph&#39;s cached template feature:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;query GetArticlesByCategory {
  ArticlePage(
    where: { TeaserText: { contains: &quot;Technology&quot; } }
    limit: 10
    locale: &quot;en&quot;
  ) {
    items {
      Name
      TeaserText
      RelativePath
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;code-block__code !my-0 !rounded-lg !text-sm !leading-relaxed&quot;&gt;&lt;br /&gt;Including the query `parameter stored=true` and the header `cg-stored-query: template`, along with this restructuring allows the translated query structure to be cached and only variable values are substituted, dramatically improving performance.&lt;/pre&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;More details on this can be found in Jonas Bergqvist&#39;s blog post listed in the Related Links below.&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;2. Cache responses at edge or client&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;&lt;span style=&quot;mso-spacerun: yes;&quot;&gt;Another advantage of using a BFF middleware would be to facilitate the caching of content coming from the Optimizely Graph API.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;In this situation, if the content rarely changes&amp;nbsp;then this could be cached within the BFF application or by providing a more fine-grained caching strategy for clients of the BFF (or CDN).&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;3. Use query fragments for reusable content blocks&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Define GraphQL fragments to standardise and optimise how frequently used structures (e.g. banners, nav items) are retrieved.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;For example, rather than repeating the sections for `` and ``, the following query has been implemented using fragments:&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;# Common image fragment
fragment ImageFields on ContentReference {
  Url
  AltText
  Width
  Height
}

# Common link fragment  
fragment LinkFields on ContentReference {
  Url
  Text
  Title
  Target
}

# Common page metadata fragment
fragment PageMetadata on IContent {
  Name
  RelativePath
  _metadata {
    published
    lastModified
    locale
  }
}

# Full query using all fragments
query GetProductPage($id: String!) {
  ProductPage(where: { _metadata: { key: { eq: $id } } }) {
    items {
      ...PageMetadata
      
      ProductName
      ProductDescription
      
      ProductImage {
        ...ImageFields
      }
      
      RelatedProducts {
        ...on ProductPage {
          ProductName
          ThumbnailImage {
            ...ImageFields
          }
          ProductLink {
            ...LinkFields
          }
        }
      }
      
      CallToAction {
        ...LinkFields
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;MsoNormal&quot; style=&quot;margin: 12.0pt 0cm 12.0pt 0cm;&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Whilst there will be a small performance gain from the (slightly) shorter query content, this has the added benefits of:&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;DRY Principle: Define field selections once, reuse everywhere&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Consistency: All queries return the same fields for the same content types&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Maintainability: Update fields in one place, all queries automatically updated&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Readability: Smaller queries are easier to read, understand and debug&lt;/span&gt;&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;mso-ascii-font-family: Aptos; mso-fareast-font-family: Aptos; mso-hansi-font-family: Aptos; mso-bidi-font-family: Aptos;&quot;&gt;Optimisation: Graph can better optimise repeated fragment usage&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;4. Avoid N+1 issues in nested queries&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;The N+1 problem occurs when you fetch a list of content items, then make separate queries to retrieve related content for each item (e.g., fetching 10 events pages, then making 10 additional queries to get each event&#39;s location). This results in poor performance.&lt;/p&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use GraphQL&#39;s nested query capabilities to fetch related content in a single request. Here is an example of this from the scenario above:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code&gt;query GetEventsWithLocations {
  EventPage(limit: 10) {
    items {
      Name
      EventDate
      Description
      LocationReference {
        ...on LocationPage {  # Expand the reference inline
          Name
          Address
          City
          PostalCode
          Country
          Latitude
          Longitude
        }
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;When querying content with &lt;code class=&quot;bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]&quot;&gt;ContentReference&lt;/code&gt; or &lt;code class=&quot;bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]&quot;&gt;ContentArea&lt;/code&gt; fields, expand those references inline using fragments rather than fetching them separately.&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;If multiple queries are unavoidable, implement caching to prevent redundant requests for the same content, or use bulk queries with the &lt;code class=&quot;bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]&quot;&gt;in&lt;/code&gt; operator to fetch multiple related items at once.&lt;/p&gt;
&lt;h3&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;Don&amp;rsquo;t:&lt;/span&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;1. Use Graph for high-frequency real-time queries (e.g. stock price tickers, rapidly changing datasets)&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;Optimizely Graph is optimised for content delivery, not real-time data streams. Whilst it can be used to serve data from external (non-Optimizely) systems, it excels with content&lt;/span&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt; that changes at human editorial pace (pages, blog articles, products, etc.) rather than data that updates multiple times per second.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;mso-fareast-font-family: Aptos;&quot;&gt;If your application requires high-frequency updates like stock price tickers, live sports scores, real-time chat messages, IoT sensor readings, or rapidly changing inventory levels, these should be served from a dedicated real-time backend (Redis, WebSockets, SignalR) or a specialised time-series database. Use Graph for what it excels at - flexible querying and delivery of editorial content.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;Running Optimizely Graph securely and efficiently in production requires balancing accessibility with control. Use Single Key authentication for public content, implement HMAC with role-based access for restricted content, and consider a Backend for Frontend (BFF) layer when exposing credentials would create security risks. Maximise performance through cached templates, query fragments, and nested queries that eliminate redundant requests.&lt;/p&gt;
&lt;p class=&quot;font-claude-response-body break-words whitespace-normal leading-[1.7]&quot;&gt;Combined with Part 1&#39;s content modeling and querying best practices, these operational guidelines ensure your Graph implementation remains secure, performant, and maintainable as your content delivery needs evolve and scale. In the final post of this series I&#39;ll be giving our best practices for managing and maintaining the implementation, including: managing API keys, integration strategies and governance.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Related Links&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/authentication&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/api-single-key-auth&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/api-single-key-auth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/hmac-auth&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/hmac-auth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/6d8bc4531b4f4d41be262205da627bce.aspx&quot;&gt;https://world.optimizely.com/forum/developer-forum/cms-12/thread-container/2025/5/graph-cms-index-jobs---ignoring-restricted-content/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/cached-templates&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/cached-templates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/b1a34cfe6a2745ae8591d40cd3eacd3b.aspx&quot;&gt;https://world.optimizely.com/blogs/Jonas-Bergqvist/Dates/2025/2/boosting-graph-query-performance-with-stored-templates/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/graphql-best-practices&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/graphql-best-practices&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-williams/dates/2026/1/optimizely-graph-best-practices---security-access-control-and-performance-optimisation/</guid>            <pubDate>Thu, 29 Jan 2026 21:49:41 GMT</pubDate>           <category>Blog post</category></item><item> <title>Optimizely Graph Best Practices - Content Modelling and Querying</title>            <link>https://world.optimizely.com/blogs/jon-williams/dates/2026/1/optimizely-graph-best-practices-pt.-1</link>            <description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;With the Mando Group team having worked extensively with Optimizely Graph over the last 12+ months, we have uncovered a number of best practices along the way.&lt;/p&gt;
&lt;p&gt;For readability, I have split the best practices across three posts. This post includes sections on content modelling and querying content within Optimizely Graph. Part 2 will contain our best practice findings relating to security &amp;amp; access control and performance optimisation and then the third on managing and maintaining the implementation, including: managing API keys, integration strategies and governance.&lt;/p&gt;
&lt;p&gt;These posts are designed for developers, solution architects, DevOps teams, and anyone responsible for building Optimizely Graph-powered applications or sites.&lt;/p&gt;
&lt;p&gt;As with a lot of best practice guides, this post leans heavily on the existing contributions of others from within the Optimizely Community and I&#39;ve given a list of related links at the bottom of the post for those that have most significantly contributed.&lt;/p&gt;
&lt;h2&gt;1. Content Modelling Best Practices&lt;/h2&gt;
&lt;p&gt;Good content modelling is essential to getting value from Graph. However, most of the items in this area are just normal content modelling best practices, rather than anything Optimizely Graph-specific. These include:&lt;/p&gt;
&lt;h3&gt;Do:&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;1. Do: Design with reuse in mind&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Use modular content types (e.g. Author, PromoBlock, CTA, FAQ) that can be linked and reused in multiple places.&lt;/p&gt;
&lt;p&gt;Doing this allows content to be shared in multiple places &amp;ndash; providing familiarity and reducing the content maintenance burden for editors.&lt;/p&gt;
&lt;p&gt;Additionally, it provides a consistent structure for Optimizely Graph content consumers (e.g. headless websites, mobile applications, etc.) and facilitates more sophisticated caching strategies.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;2. Do: Use structured fields&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Favour structured fields (int, bool, DateTime, ContentReference, etc.) over (plain or rich) text fields where appropriate. This allows cleaner queries against these fields and more reliable filtering.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;3. Do: Establish meaningful relationships&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Use ContentArea, ContentReference, and ContentReferenceList fields to link content objects logically (e.g. a BlogPost with related Author, Tags, Category, or PromoBlock).&lt;/p&gt;
&lt;p&gt;Whilst having more generic content types (e.g. &#39;RichTextField&#39;) may reduce the overall number of content types, it makes understanding and working with the content less intuitive.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;4. Do: Use naming conventions consistently&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Standardise field names to simplify query building and team handovers.&lt;/p&gt;
&lt;p&gt;For example, don&#39;t call the main H1 field &#39;Title&#39; in one content type and then &#39;Heading&#39; in another defined content type.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;5. Do: Set PropertyIndexMode correctly&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;As stated in the online documentation (&lt;a href=&quot;https://docs.developers.optimizely.com/content-management-system/docs/install-and-configure-optimizely-graph-on-your-site#property-index-modes&quot;&gt;here&lt;/a&gt;), if you know for sure that a particular field within a page or block will not be used for filtering or searching on then you can set the `OutputOnly` mode using the following syntax:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[GraphProperty(PropertyIndexingMode.OutputOnly)]&lt;/code&gt;&lt;br /&gt;&lt;code&gt;public virtual string Description { get; set; }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Additionally, if you want the field to be searchable (using a &lt;strong&gt;where&lt;/strong&gt; clause) but it does not need to be searchable with &lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/full-text-search-support&quot;&gt;full-text search&lt;/a&gt; then you can set this as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[GraphProperty(PropertyIndexingMode.Default)]&lt;/code&gt;&lt;br /&gt;&lt;code&gt;public virtual string Description { get; set; }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Just be mindful that if the Graph client requirements change around these fields then you&#39;ll need to make the necessary attribute change/removal, re-deploy the application and re-index the Graph content.&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3&gt;Don&#39;t:&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;1. Don&#39;t: Use website-specific field names&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Keep in mind that content stored in Graph may be used in lots of different contexts (e.g. Website, mobile app, kiosk application, etc.) and avoid using field names that only make sense in one of these.&lt;/p&gt;
&lt;p&gt;For example, don&#39;t call a field `RightColumnText` if the content could also be used on a mobile app where the content is shown in a single column. Instead, name the field something like `SecondaryContentText` - which makes sense in both contexts.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;2. Don&#39;t: Overuse XhtmlString (a.k.a. Rich text) fields&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Breaking larger blocks of rich text into more structured, separate fields may make the content more flexible and reuse simpler.&lt;/p&gt;
&lt;p&gt;For example, rather than having a rich text field that contains some formatted text, an image and a table, split this content into separate fields to allow each part to be used independently (without the need for additional client-side processing).&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;3. Don&#39;t: Duplicate similar content types across sites or channels&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Having consistent content types across as much of the client&#39;s digital estate as possible makes reuse simpler. For example, don&#39;t have a &#39;Blog Article&#39; content type on their main site and then a different &#39;Blog Post&#39; content type on one of their microsites &amp;ndash; Having shared content model projects allows reuse of content types as much as possible.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;2. Querying Best Practices&lt;/h2&gt;
&lt;h3&gt;Do:&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;1. Do: Use specific, shallow queries&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Avoid querying deeply nested objects unless required. Shallow, purpose-specific queries are faster and more maintainable.&lt;/p&gt;
&lt;p&gt;Request only the fields that you will use on your frontend. There can sometimes be a temptation to fetch additional fields for testing or verification purposes. Ensure that you remove these from your final queries.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;2. Do: Paginate large result sets&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Optimizely Graph has two mechanisms for paginating large data sets: Cursor-Based vs Offset Pagination.&lt;/p&gt;
&lt;p&gt;In line with the Optimizely documentation (&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/cursor&quot;&gt;here&lt;/a&gt;), using the traditional offset pagination (using the standard &#39;skip&#39; and &#39;limit&#39; parameters) is typically more efficient on smaller data sets (e.g. fewer than 10,000 results), but the selected mechanism should depend on your individual use case.&lt;/p&gt;
&lt;p&gt;Whichever approach, the principle still applies that selecting only the number of results needed, and not needing to discard results, is far more efficient.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;3. Do: Use variables for flexibility&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Define filters and projections as GraphQL variables to avoid hardcoding and to support front-end reuse.&lt;/p&gt;
&lt;p&gt;Always use GraphQL variables instead of hardcoding values directly into your queries.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# Instead of hardcoding values:&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;query { BlogPost(where: { Status: { eq: &quot;Published&quot; } }, limit: 50) { ... } }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;# Use variables:&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;query GetBlogPosts($status: String!, $limit: Int!) {&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;nbsp; BlogPost(where: { Status: { eq: $status } }, limit: $limit) { ... }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Doing it this way allows for using cached templates and queries (which I will cover in the second post) &amp;ndash; providing significant efficiency gains. However, beyond performance, variables also enable query reusability across components, provide type safety and validation, prevent injection attacks, and make queries easier to maintain.&lt;/p&gt;
&lt;p&gt;Ensure that you define explicit types for all variables and use non-null types (!) when values are required. This is particularly valuable in component-based frameworks where the same query can be shared across multiple components with different parameter values.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;4. Do: Filter and sort server-side (i.e. Within the Graph query)&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;A broad rule of thumb should be to apply where and order conditions within Graph queries rather than handling data manipulation in the client-side.&lt;/p&gt;
&lt;p&gt;The where clause allows you to filter content based on property values, reducing the amount of data transferred and improving response times. However, not all filtering approaches are created equal.&lt;/p&gt;
&lt;p&gt;Use exact matches and equality operators (eq, in) whenever possible, as these execute faster than partial matches or complex string operations. For example, filtering by content type, status, or ID is highly efficient, while using contains or startsWith on large text fields requires more processing.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;5. Do: Experiment and consider alternative options&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Despite the broad-brush best practice guidelines above, I would still recommend testing your queries and considering all approaches.&lt;/p&gt;
&lt;p&gt;For example, if you know that your website visitors almost always scroll to view more articles that are dynamically loaded, then pre-fetching these with a slightly less efficient Graph query (with a bigger page size) and hiding/caching the extra values may provide a faster and more enjoyable user experience.&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3&gt;Don&#39;t:&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;1. Query entire collections with no limits&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Avoid querying large collections without specifying pagination parameters. Queries like &lt;code&gt;BlogPost { items { ... } }&lt;/code&gt; without a &lt;code&gt;first&lt;/code&gt; or &lt;code&gt;limit&lt;/code&gt; parameter will attempt to retrieve all matching content, which can cause serious performance issues, timeouts, and excessive memory consumption (on both the server and client).&lt;/p&gt;
&lt;p&gt;Optimizely Graph enforces limits, but relying on default behaviours is risky. In production environments with thousands of content items, an unlimited query can easily timeout or overwhelm your application&#39;s memory, particularly on mobile devices or lower-powered clients.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;2. Request unnecessary fields &quot;just in case&quot; &amp;mdash; this increases payload and processing time&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Avoid the temptation to request fields that you don&#39;t immediately need in your frontend. Queries that fetch every available field&amp;mdash;or include extra fields for testing, debugging, or potential future use&amp;mdash;significantly increase payload size, processing time, and network transfer costs.&lt;/p&gt;
&lt;p&gt;GraphQL&#39;s primary advantage is its ability to request exactly the data you need, nothing more. When you query for 20 fields but only render 5, you&#39;re wasting resources on both the server (which must retrieve and serialize the extra data) and the client (which must parse and store it). This is particularly problematic on mobile devices or slower connections where bandwidth and processing power are limited.&lt;/p&gt;
&lt;p&gt;It&#39;s common during development to fetch additional fields for verification or debugging purposes. However, these extra fields often remain in production queries long after they&#39;re no longer needed, quietly degrading performance.&lt;/p&gt;
&lt;p&gt;Regularly audit your queries as part of code reviews or performance optimization sessions. Lean queries result in faster response times, reduced bandwidth usage, and better overall application performance.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;Effective use of Optimizely Graph starts with thoughtful content modelling and efficient querying practices. By designing reusable, well-structured content types with consistent naming conventions and appropriate indexing modes, you create a foundation that scales across multiple channels and applications. Similarly, crafting specific, shallow queries with proper pagination and server-side filtering ensures optimal performance and maintainability.&lt;/p&gt;
&lt;p&gt;The practices outlined in this post - from avoiding deeply nested queries to leveraging GraphQL variables for flexibility - will help you build faster, more reliable Optimizely Graph implementations. Remember that while these guidelines provide a strong framework, every project has unique requirements, so testing and measuring performance in your specific context remains essential.&lt;/p&gt;
&lt;p&gt;In the subsequent posts, we&#39;ll dive into the operational aspects of running Optimizely Graph in Production, including performance optimisation techniques, security considerations, API key management strategies, integration patterns, and governance approaches. These additional practices will help ensure your Graph implementation remains secure, performant, and maintainable over time.&lt;/p&gt;
&lt;p&gt;Stay tuned for Part 2, which will be published in the coming weeks.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Related Links&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/introduction-optimizely-graph&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/introduction-optimizely-graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.developers.optimizely.com/platform-optimizely/docs/cursor&quot;&gt;https://docs.developers.optimizely.com/platform-optimizely/docs/cursor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oshyn.com/blog/optimizely-graph&quot;&gt;https://www.oshyn.com/blog/optimizely-graph&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/7cb83a6c7b5b4d06b43ae624da761285.aspx&quot;&gt;https://world.optimizely.com/blogs/nguyen-nguyen/dates/2024/3/exclude-cms-content-properties-from-being-indexed-in-optimizely-graph/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-williams/dates/2026/1/optimizely-graph-best-practices-pt.-1</guid>            <pubDate>Fri, 16 Jan 2026 06:43:03 GMT</pubDate>           <category>Blog post</category></item><item> <title> Opti ID: What is it and why now is a good time to use it</title>            <link>https://world.optimizely.com/blogs/jon-williams/dates/2025/11/-optiid-what-is-it-and-why-you-need-it-now/</link>            <description>&lt;p class=&quot;MsoNormal&quot;&gt;If you&amp;rsquo;ve been hearing the term&amp;nbsp;&lt;strong&gt;Opti ID&lt;/strong&gt; floating around and wondering what the fuss is about, let&amp;rsquo;s break it down in plain English.&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;What is Opti ID at a high level?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Think of Opti ID as your&amp;nbsp;&lt;strong&gt;one key to the Optimizely kingdom&lt;/strong&gt;. Instead of juggling multiple logins for CMS, CMP, DXP, and other Optimizely tools, Opti ID gives you a single, secure identity across the board. It&amp;rsquo;s like having one passport for all the countries in the Optimizely world.&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;What advantages does it bring?&lt;/h2&gt;
&lt;ul style=&quot;margin-top: 0cm;&quot;&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l2 level1 lfo1; tab-stops: list 36.0pt;&quot;&gt;&lt;strong&gt;One login, less hassle&lt;/strong&gt; &amp;ndash; No more remembering five different passwords.&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l2 level1 lfo1; tab-stops: list 36.0pt;&quot;&gt;&lt;strong&gt;Better security&lt;/strong&gt; &amp;ndash; MFA support and modern protocols keep things locked down.&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l2 level1 lfo1; tab-stops: list 36.0pt;&quot;&gt;&lt;strong&gt;Smooth onboarding&lt;/strong&gt; &amp;ndash; SCIM integration means user and group management is automated.&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l2 level1 lfo1; tab-stops: list 36.0pt;&quot;&gt;&lt;strong&gt;Future-proof&lt;/strong&gt; &amp;ndash; Opti ID is becoming the standard for all Optimizely services.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;image&quot;&gt;&lt;img style=&quot;border-style: solid;&quot; src=&quot;/link/d9cf751fefe14c83bbf7ecb114e537f2.aspx&quot; alt=&quot;OptiID login screen&quot; width=&quot;1084&quot; height=&quot;626&quot; /&gt;
&lt;figcaption&gt;Unbranded Opti ID login screen&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;What will happen if you don&amp;rsquo;t have Opti ID?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;If you regularly work in the Optimizely ecosystem then you&amp;rsquo;ll start hitting roadblocks.&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Some new services (like &lt;a href=&quot;https://www.mandogroup.com/news-insights/what-makes-optimizely-opal-ai-different&quot;&gt;&lt;strong&gt;Optimizely&#39;s Opal AI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;functionality) will require Opti ID from the outset and other existing systems, such as the login to Optimizely World, are&amp;nbsp;&lt;a href=&quot;/link/b80a72006566431baba5090b28f6c124.aspx&quot;&gt;moving over to it&lt;/a&gt;. Without and Opti ID login, you&amp;rsquo;ll be stuck with fragmented access to Optimzely systems and manual user management. Basically, life gets harder.&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;What does this mean in the real world?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Picture this:&lt;/p&gt;
&lt;ul style=&quot;margin-top: 0cm;&quot;&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l3 level1 lfo2; tab-stops: list 36.0pt;&quot;&gt;You&amp;rsquo;re an editor working on CMS content, then need to jump into CMP for campaign planning or to upload a DAM asset. With Opti ID, you log in once and move seamlessly between these tools. Without it, you&#39;ll need to remember and input two separate passwords (and possibly usernames) for each of the systems - causing a break in your flow and frustration.&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l3 level1 lfo2; tab-stops: list 36.0pt;&quot;&gt;Need to manage permissions for your team? Instead of fiddling with settings in multiple separate systems (CMS, CMP, ODP, etc.), you can do it centrally via Opti ID - being able to see exactly which systems a user has access to and which groups they are a member of in one place.&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l3 level1 lfo2; tab-stops: list 36.0pt;&quot;&gt;Concerned about a bad guy guessing a password, logging into your CMS and inflicting significant reputational damage (and potentially locking everyone else out of the CMS)? You might want to implement multi-factor authentication (MFA) sooner rather than later. Luckily, that&#39;s baked into Opti ID too.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;image&quot;&gt;&lt;img src=&quot;/link/2539b78993e144d19a9854e3f605dc10.aspx&quot; alt=&quot;Multi-factor authentication enabled within OptiID&quot; width=&quot;910&quot; height=&quot;591&quot; /&gt;
&lt;figcaption&gt;Multi-factor authentication setting enabled within the Admin Centre&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;I&#39;m interested. What do I need to consider?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;There are a few things to consider before deciding whether to move over to using Opti ID. Some questions you will want to think about include:&lt;/p&gt;
&lt;ol style=&quot;margin-top: 0cm;&quot;&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;Do you need access to Optimizely systems such as Helpdesk support, Optimizely World, Optimizely Academy, etc? (Hint: If the answer to this is &#39;yes&#39; then you will almost certainly need an Opti ID account.)&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;Are you using more than one product from the Optimizely platform (e.g. CMS, CMP, ODP, etc.)?&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;Are you using only Optimizely SaaS products (e.g. ODP, Web Experimentation, etc.) or do we need some small additional configuration and code changes to make this work (e.g. on PaaS CMS)?&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;Do you need the additional security of multi-factor authentication (MFA) on our site or is a simple username and password still sufficient?&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;Are you happy having a separate username and password (and optionally MFA) for Opti ID or do we want to tie this into our existing authentication system (e.g. Microsoft Entra ID, Okta, etc.)?&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;Do you want to automatically sync users and groups from our existing authentication system into Opti ID or are we happy to manually create/duplicate these?&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;How will you we manage the roll out and communication around this change?&lt;/li&gt;
&lt;li class=&quot;MsoNormal&quot; style=&quot;mso-list: l1 level1 lfo3; tab-stops: list 36.0pt;&quot;&gt;How will you test this to ensure that all login flows work (for all user types on all systems) before turning off the old authentication mechanisms?&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;I already log in to my laptop. Why can&amp;rsquo;t It just use that authentication?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Good question! It actually &lt;strong&gt;can&lt;/strong&gt;. If your organisation uses &lt;strong&gt;Entra ID (formerly Azure AD)&lt;/strong&gt; or another OIDC-compliant provider such as Okta or PingOne, you can configure Opti ID to trust that identity (rather than having a separate Opti ID username and password). So yes, your laptop login can carry over &amp;ndash; you just need to set up the connection within the Optimizely Admin Centre.&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Side note: Opti ID also supports SAML based authorisation to allow connectivity to legacy identity providers or those with OIDC restrictions.&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;How do I manage groups and permissions?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Users and groups can be easily created and centrally managed within the Optimizely &lt;strong&gt;Admin Centre&lt;/strong&gt;. However, many organisations don&#39;t want to duplicate these (in Opti ID) and instead just want control them within their existing identity provider (e.g. Entra ID or Okta). To facilitate this, Opti ID supports &lt;strong&gt;SCIM provisioning&lt;/strong&gt;, which means you can sync users and groups from your existing identity provider into the Opti ID platform. No need to duplicate this group membership configuration in two places or to manually add (potentially) hundreds of users within the Opti ID system!&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;image&quot;&gt;&lt;img src=&quot;/link/a20c787e0496482780ee40b9abdf60d9.aspx&quot; alt=&quot;OptiID Admin Centre - User management screen&quot; width=&quot;1114&quot; height=&quot;347&quot; /&gt;
&lt;figcaption&gt;Admin Centre - User management screen&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;I&amp;rsquo;ve not had to use this before. Why should I set up Opti ID now?&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;As mentioned above, new services like &lt;strong&gt;Opal&lt;/strong&gt; already require it and many others, such as access to Optimizely World, Optimizely Academy and Support, are following suit. Setting it up now saves headaches later and gives you a single user account to access to the necessary systems.&lt;/p&gt;
&lt;div class=&quot;MsoNormal&quot; style=&quot;text-align: center;&quot; align=&quot;center&quot;&gt;&lt;hr /&gt;&lt;/div&gt;
&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;Opti ID isn&amp;rsquo;t just another login system &amp;ndash; it&amp;rsquo;s the backbone of how Optimizely is moving forward. Get ahead of the curve, make life easier for your team, and lock down security while you&amp;rsquo;re at it.&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;If you need help understanding Opti ID, its benefits or technicalities further then please get in touch.&lt;/p&gt;
&lt;p class=&quot;MsoNormal&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Related Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;!-- [if !supportLists]--&gt;&lt;a href=&quot;https://support.optimizely.com/hc/en-us/articles/32694161850381-Overview-of-Opti-ID&quot;&gt;https://support.optimizely.com/hc/en-us/articles/32694161850381-Overview-of-Opti-ID&lt;/a&gt;&lt;!-- [if !supportLists]--&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/b80a72006566431baba5090b28f6c124.aspx&quot;&gt;https://world.optimizely.com/blogs/satata-satez/dates/2025/9/world-login-is-moving-to-optiid/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.optimizely.com/hc/en-us/articles/25450783599117-Overview-of-the-Opti-ID-Admin-Center&quot;&gt;https://support.optimizely.com/hc/en-us/articles/25450783599117-Overview-of-the-Opti-ID-Admin-Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.optimizely.com/hc/en-us/articles/22954897492109-2025-Opti-ID-release-notes&quot;&gt;https://support.optimizely.com/hc/en-us/articles/22954897492109-2025-Opti-ID-release-notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.optimizely.com/hc/en-us/articles/32769522265485-Overview-of-SCIM-provisioning-for-Opti-ID&quot;&gt;https://support.optimizely.com/hc/en-us/articles/32769522265485-Overview-of-SCIM-provisioning-for-Opti-ID&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>            <guid>https://world.optimizely.com/blogs/jon-williams/dates/2025/11/-optiid-what-is-it-and-why-you-need-it-now/</guid>            <pubDate>Wed, 12 Nov 2025 14:38:37 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>