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
item for single resultsUsing 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
- Request only the needed fields to improve performance.
- Use pagination for large result sets.
- Batch related queries when possible.
- 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_floatwith scale of 1000).Values like
12.34567are rounded to12.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
- Cache frequently used queries when possible.
- Use appropriate indices for filtering.
- Monitor query performance and optimize slow queries.
- 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
}
}
}Updated 16 days ago
