Limits
HTTP payload caps, timeouts, persisted-query modes, executor selection safeguards - contain abusive graphs before resolver work dominates.
Use this guide to set the outer request budget before resolver work starts. Combine HTTP body limits, execution timeouts, document-shape limits, and trusted documents according to the traffic your service accepts.
Even well‑formed GraphQL documents can overwhelm memory or CPU (alias bombs, multi‑megabyte JSON bodies). Separate these controls from masking/auth (Security) and schema discovery knobs (Introspection).
Payload & timeouts
| Control | Goal | grx helper (grx.NewServer) | Only server.Config |
|---|---|---|---|
| HTTP envelope | Oversized POST JSON bodies | WithMaxHTTPRequestBytes(n) | MaxHTTPRequestBytes |
| Variables JSON | Oversized variables payloads | - | MaxVariableBytes |
| Clock guard | Hanging resolvers | WithRequestTimeout(d) | RequestTimeout |
package main
import (
"log"
"time"
"example.com/hello-grx/graph"
"github.com/grx-gql/grx"
"github.com/grx-gql/grx/server"
)
func main() {
var err error
_, err = grx.NewServer(
grx.WithSchema(graph.Schema()),
grx.WithRequestTimeout(15*time.Second),
grx.WithMaxHTTPRequestBytes(1<<20),
grx.WithMaxSelectionDepth(16),
)
if err != nil {
log.Fatal(err)
}
_, err = server.New(server.Config{
Schema: graph.Schema(),
RequestTimeout: 30 * time.Second,
MaxHTTPRequestBytes: 2 << 20,
MaxVariableBytes: 96 << 10,
})
if err != nil {
log.Fatal(err)
}
}Persisted & trusted corpus
WithPersistedQueries maps sha256 → literal query. Harden server.Config with RequirePersistedQuery, StrictPersistedQueries, TrustedDocuments, RejectUnknownVariables for closed corpora (server package tests demonstrate behaviour).
Extended procedure: Persisted queries (APQ).
Document-shape safeguards
Executors reject parses that explode combinationally (Execution pipeline).
| Mechanism | Source |
|---|---|
| Total selections | server.Config.MaxSelectionCount |
| Aliases | MaxAliasCount |
| Parallel root fields | MaxRootFieldCount |
| Deepest nesting | grx.WithMaxSelectionDepth(n) / server.Config.MaxSelectionDepth |
package main
import (
"log"
"example.com/hello-grx/graph"
"github.com/grx-gql/grx/server"
)
func main() {
srv, err := server.New(server.Config{
Schema: graph.Schema(),
MaxSelectionDepth: 16,
MaxSelectionCount: 750,
MaxAliasCount: 200,
MaxRootFieldCount: 10,
})
if err != nil {
log.Fatal(err)
}
_ = srv
}Patterns + rationale: Query & document limits.
Limits ≠ deterministic cost modelling
Counters are guardrails - not Apollo-style deterministic cost engines.
Last updated on