yireo / magento2-custom-graph-ql-query-limiter

yireo/magento2-custom-graph-ql-query-limiter

Magento 2 module to sync a GraphQL session with the regular session

  • Jisse Reitsma (Yireo)
magento2-module Compatibility: 2.4.7-2.4.9 Code Quality: Fail Tests: Fail Security: Pass OSL-3.0

Yireo CustomGraphQlQueryLimiter

Magento 2 module to customize settings for the GraphQL Query Limiter to enhance performance and security of your headless Magento.

Installation

Install via composer (composer require yireo/magento2-custom-graph-ql-query-limiter), enable the module Yireo_CustomGraphQlQueryLimiter, refresh caching and do your magic with DI compilation, static content and database upgrades.

Usage

The Yireo CustomGraphQlQueryLimiter module allows you to modify the query depth and the query complexity in an easy way, by simply letting you change these values from the Magento Admin Panel. Simply navigate to the Store Configuration in your backend and then to Yireo > Yireo CustomGraphQlQueryLimiter > Settings and set the desired values.

Additionally, it also enables these settings in the Developer Mode, while Magento by default only enables this in Production Mode. It makes it easier to test things, instead of bumping into potential issues early.

Once you update the settings, make sure to test this with an entire client-side app including complexer GraphQL queries, mutations and fragments (for instance, within Magento PWA Studio), because it potentially break your app.

Introduction

Magento 2.3+ ships with a GraphQL API that allows you to make simple queries like these:

{
  products(filter: {name: {match: "jacket"}}) {
    items { sku }
  }
}

Based upon the same kind of query, you can also create a recursive lookup of products and categories, which might be looking like this:

{
  products(filter: {name: {match: "jacket"}}) {
    items {
      sku
      categories {
        products {
          items {
            sku
            categories {
              products {
                items {
                  sku
                  categories {
                    products {
                      items {
                        sku
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

In my development environment, this quickly leads to timeouts, proofing that this type of query might not be benefiting a production environment, to put it lightly.

Magento 2 its GraphQL system is based on the Webonyx GraphQL PHP library, which offers a couple of security mechanisms to prevent this kind of query from being handled: Query depth and query complexity. The Magento 2 core uses a DI type to set values for this, which could be overridden using your own DI type:

<type name="Magento\Framework\GraphQl\Query\QueryComplexityLimiter">
    <arguments>
        <argument name="queryDepth" xsi:type="number">20</argument>
        <argument name="queryComplexity" xsi:type="number">300</argument>
    </arguments>
</type>

Looking at the culprit query above, the depth is 10: Simply counting the opening curly braces { from the start of the return statement (items). By setting the queryDepth to 7 or 8, the query would generate an error instead:

{
  "errors": [
    {
      "message": "Max query depth should be 7 but got 10.",
      "extensions": {
        "category": "graphql"
      }
    }
  ]
}

Setting the complexity

The complexity could be modified as well. Looking at the culprit query above, the complexity is 15. It proves that the complexity of a GraphQL query might be quite low, but still the impact could be high. However, setting the complexity to 300 seems rather high. Perhaps in your case, setting it to 50 might be a better idea.

The Webonyx library also allows you to add a complexity function to a specific field definition. Theoretically, this is something that would need to be customized per query (categories, products). What makes a specific query less performant and would therefore need to be labeled as complex?

Note that setting an empty value on either query depth or complexity in the database, will make the value to be skipped. At that moment, the original DI configuration is taken into account.

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.

[Unreleased]

[0.0.6] - 14 August 2025

Fixed

  • Switch $source type from string to DocumentNode|string

[0.0.5] - 12 August 2025

Fixed

  • Fix implicit nullables for PHP 8.4
  • PHP 8.2 upgrades
  • Upgrade PHPStan workflow

[0.0.4] - 12 April 2024

Fixed

  • Changed method arguments in M 2.4.7

[0.0.3] - 9 February 2022

Fixed

  • Fixed issue with new validateFieldCount() in 2.4.3 (issued by @youanden)
  • Removed setup_version from module.xml

[0.0.2] - 29 July 2020

Added

  • Magento 2.4 compatibility

[0.0.1] - Undocumented

Versions
Version Stability QA Status Compatibility Released
0.0.6 stable Fail Magento 2.4.7-2.4.9 Details 2025-08-14 09:37:53
0.0.5 stable Not tested Not yet tested Details 2025-08-12 05:59:50
0.0.4 stable Not tested Not yet tested Details 2024-04-12 09:29:00
0.0.3 stable Not tested Not yet tested Details 2022-02-09 15:38:13
0.0.2 stable Not tested Not yet tested Details 2021-02-18 09:54:32

Requires 4

Package Constraint
magento/framework ^100.1|^101.0|^102.0|^103.0
magento/module-checkout ^100.1
magento/module-quote ^100.1|^101.0
php ^8.0

Requires-dev 2

Package Constraint
phpunit/phpunit *
yireo/magento2-integration-test-helper @dev

Compatibility

Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.

Compatibility matrix (Magento × PHP)
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 Pass Pass
2.4.9 Pass Pass

Code Quality

Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge — a phpcs finding can't make a module incompatible.

Static analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

Static analysis results
Tool Status Findings Summary
PHPCS Pass 0
PHPMD Warning 1 1 rule violation (UnusedFormalParameter:1)
Cpd Pass 0
Composer validate Info 1 valid; 1 advisory note (composer validate --strict)

PHPStan

Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases. Cell → details modal.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 2 2
2.4.8 2 2
2.4.9 2 2

Tests

Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.

Unit tests

Unit tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Integration tests

Integration tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Error Error
2.4.8 Error not tested
2.4.9 Error not tested

Security

Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.

Security results
Tool Status Findings Summary
Composer audit Pass 0
Malware scan Pass 0
License
OSL-3.0
Homepage
https://github.com/yireo/Yireo_CustomGraphQlQueryLimiter
Authors

More from yireo

View vendor
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.