NestedGraphQLQuery
NestedGraphQLQuery
Severity: warning | Type: LiquidHtml
This check detects {% graphql %} tags placed inside loop tags ({% for %}, {% tablerow %}), which causes one database request per loop iteration — the classic N+1 pattern. It also follows {% function %} and {% render %} calls transitively to detect indirect GraphQL queries.
The N+1 problem often arises when dealing with related records. To address it, fetch all required data in a single query before the loop and pass it as a variable.
Exceptions: GraphQL inside {% background %} or {% cache %} blocks within a loop is not flagged, as those contexts have different performance characteristics.
Examples
✗ Incorrect Code Example (Avoid using this):
Direct GraphQL in a loop:
{% assign arr = 'a,b,c' | split: ',' %}
{% for el in arr %}
{% graphql g = 'my/graphql', el: el %}
{{ g.records.results[0].id }}
{% endfor %}
Transitive GraphQL via function call in a loop:
{% for item in items %}
{% function result = 'lib/fetch_item_data', id: item.id %}
{% endfor %}
Where lib/fetch_item_data internally calls {% graphql %}.
✓ Correct Code Example (Use this instead):
{% assign arr = 'a,b,c' | split: ',' %}
{% graphql g = 'my/graphql', arr: arr %}
{% for el in arr %}
{% comment %}Use data from g here{% endcomment %}
{% endfor %}
For related records, use the related_records approach to fetch all data in a single query.
Configuration
The default configuration for this check:
NestedGraphQLQuery:
enabled: true
severity: warning
Disabling This Check
Ideally, there should be no need to disable this check. platformOS provides alternative solutions for all scenarios that would otherwise require a GraphQL query inside a loop.