Estimators

An estimator is the strategy that decides how much complexity to assign to each field in a GraphQL query. graphql-complexity ships with three built-in estimators that cover the most common use cases.


SimpleEstimator

SimpleEstimator assigns a constant complexity value to every field. Nested fields are multiplied together as the algorithm descends the query tree, so deeper queries naturally cost more.

Usage

from graphql_complexity import SimpleEstimator

estimator = SimpleEstimator(complexity=1)

Parameters

Parameter

Type

Default

Description

complexity

int

1

Complexity score assigned to each field

Example

from graphql_complexity import get_complexity, SimpleEstimator
from graphql import build_schema

schema = build_schema("""
    type Post {
        title: String
        body: String
    }
    type Query {
        post: Post
    }
""")

query = """{ post { title body } }"""

# Each field costs 1 point — post + title + body = 3
complexity = get_complexity(query=query, schema=schema, estimator=SimpleEstimator(complexity=1))
print(complexity)  # 3

DirectivesEstimator

DirectivesEstimator lets you annotate individual fields in your schema with a @complexity directive, giving you fine-grained control over which fields are expensive.

Fields without the directive receive a default cost of 1.

Schema Directive

You must include the directive definition in your schema:

directive @complexity(
  value: Int!
) on FIELD_DEFINITION

Usage

from graphql_complexity import DirectivesEstimator

schema = """
directive @complexity(
  value: Int!
) on FIELD_DEFINITION

type Query {
  cheapField: String @complexity(value: 1)
  expensiveField: String @complexity(value: 10)
  defaultField: String
}
"""

estimator = DirectivesEstimator(schema)

Full Example

from graphql_complexity import get_complexity, DirectivesEstimator
from graphql import build_schema

raw_schema = """
directive @complexity(value: Int!) on FIELD_DEFINITION

type User {
    id: ID!
    name: String!
    posts: [Post] @complexity(value: 5)
}

type Post {
    title: String
    body: String @complexity(value: 3)
}

type Query {
    user: User @complexity(value: 2)
}
"""

schema = build_schema(raw_schema)

query = """
    query {
        user {
            id
            name
            posts {
                title
                body
            }
        }
    }
"""

estimator = DirectivesEstimator(raw_schema)
complexity = get_complexity(query=query, schema=schema, estimator=estimator)
print(complexity)

ArgumentsEstimator

ArgumentsEstimator scales the complexity of a field by the value of one of its numeric arguments (e.g. limit, first) or by the length of a list argument (e.g. ids). This makes queries that fetch more items cost proportionally more.

Fields with no matching argument fall back to default_complexity.

Usage

from graphql_complexity import ArgumentsEstimator

estimator = ArgumentsEstimator(
    multipliers=["limit", "first", "ids"],
    default_complexity=1,
)

Parameters

Parameter

Type

Default

Description

multipliers

list[str]

Argument names to inspect for a multiplier value

default_complexity

int

1

Base complexity score per field, multiplied by the argument value

How the multiplier is resolved

  1. The estimator walks the field’s arguments in query order and stops at the first name that appears in multipliers.

  2. If the matching argument value is an integer, that integer is used as the multiplier.

  3. If the matching argument value is a list, the length of the list is used.

  4. If the value is any other type (e.g. a string), or no argument matches, the multiplier is 1 and the field costs default_complexity.

Example

from graphql_complexity import get_complexity, ArgumentsEstimator
from graphql import build_schema

schema = build_schema("""
    type Query {
        books(limit: Int, ids: [String]): String
        version: String
    }
""")

estimator = ArgumentsEstimator(multipliers=["limit", "ids"], default_complexity=1)

# limit: 10  →  1 * 10 = 10
complexity = get_complexity(
    query="{ books(limit: 10) }",
    schema=schema,
    estimator=estimator,
)
print(complexity)  # 10

# ids: ["a", "b", "c"]  →  1 * 3 = 3
complexity = get_complexity(
    query='{ books(ids: ["a", "b", "c"]) }',
    schema=schema,
    estimator=estimator,
)
print(complexity)  # 3

# No matching argument  →  default_complexity = 1
complexity = get_complexity(
    query="{ version }",
    schema=schema,
    estimator=estimator,
)
print(complexity)  # 1

Choosing an Estimator

Use Case

Recommended Estimator

Simple uniform pricing per field

SimpleEstimator

Different costs per field, controlled in schema

DirectivesEstimator

Pricing based on pagination / list size arguments

ArgumentsEstimator

Programmatic or dynamic pricing logic

Custom Estimator


Credits

The estimator concept was inspired by graphql-query-complexity.