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 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 |
|---|---|---|---|
|
|
— |
Argument names to inspect for a multiplier value |
|
|
|
Base complexity score per field, multiplied by the argument value |
How the multiplier is resolved¶
The estimator walks the field’s arguments in query order and stops at the first name that appears in
multipliers.If the matching argument value is an integer, that integer is used as the multiplier.
If the matching argument value is a list, the length of the list is used.
If the value is any other type (e.g. a string), or no argument matches, the multiplier is
1and the field costsdefault_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 |
|
Different costs per field, controlled in schema |
|
Pricing based on pagination / list size arguments |
|
Programmatic or dynamic pricing logic |
Credits¶
The estimator concept was inspired by graphql-query-complexity.