Docs
Launch GraphOS Studio

Enforcing operation limits in the Apollo Router

With GraphOS Enterprise


This feature is only available with a

.
You can test it out by signing up for a free
Enterprise trial
.

You can define operation limits in your 's configuration to reject potentially malicious requests. An that exceeds any specified limit is rejected (unless you run your router in

warn_only mode
).

Setup

To use operation limits, you must run v1.17 or later of the .

You define operation limits in your router's

, like so:

router.yaml
limits:
max_depth: 100
max_height: 200
max_aliases: 30
max_root_fields: 20
# Uncomment to enable warn_only mode
# warn_only: true

Each limit takes an integer value. You can define any combination of

.

Supported limits

max_depth

Limits the deepest nesting of selection sets in an operation, including in .

The GetBook operation below has depth three:

query GetBook {
book { # Depth 1 (root field)
...bookDetails
}
}
fragment bookDetails on Book {
details { # Depth 2 (nested under `book`)
... on ProductDetailsBook {
country # Depth 3 (nested under `details`)
}
}
}

max_height

Limits the number of unique fields included in an operation, including fields of fragments. If a particular field is included multiple times via , it's counted only once.

The GetUser operation below has height three:

query GetUser {
user { # 1
id # 2
name # 3
username: name # Aliased duplicate (not counted)
}
}

Each unique increments an operation's height by one, regardless of that field's return type (, object, or list).

max_aliases

Limits the total number of fields in an operation, including fields of fragments.

The GetUser operation below includes three aliases:

query GetUser {
user {
nickname: name # 1
username: name # 2
handle: name # 3
}
}

Each aliased field increments the alias count by one, regardless of that field's return type (scalar, object, or list).

max_root_fields

Limits the number of root fields in an operation, including root fields in fragments. If a particular root field is included multiple times via aliases, each usage is counted.

The following operation includes three root fields:

query GetTopProducts {
topBooks { # 1
id
}
topMovies { # 2
id
}
topGames { # 3
id
}
}

warn_only mode

If you run your router in warn_only mode, that exceed defined limits are not rejected. Instead, the router processes these operations as usual and emits a WARN trace that notes all exceeded limits, like so:

2023-03-15T19:08:23.123456Z WARN apollo_router::operation_limits: max_depth exceeded, max_depth: 3, current_op_depth: 5, operation: "query GetOwnerLocation {cat {owner {location {postalCode}}}}"

Running in warn_only mode can be useful while you're testing to determine the most appropriate limits to set for your .

You can enable or disable warn_only mode in your router's

, like so:

router.yaml
limits:
warn_only: true # warn_only mode always enabled

Response format for exceeded limits

Whenever your router rejects a request because it exceeds an operation limit, the router responds with a 400 HTTP status code and a standard error response body:

# HTTP 400
{
"data": {},
"errors": [
{
"message": "Maximum height (field count) limit exceeded in this operation",
"extensions": {
"code": "MAX_HEIGHT_LIMIT"
}
}
]
}

If you run your router in

, the router logs the limit violation but executes the operation as normal, returning a 200 status code with the expected response.

Previous
Subgraph Authentication
Next
Safelisting with persisted queries
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company