grx

Persisted queries (APQ)

Ship SHA-256 registered queries and optional hardened modes - reduce payload variance and tame public POST surfaces.

Use persisted queries when you want a known query corpus, smaller repeat requests, or tighter control over public GraphQL operations. They reduce payload variance but do not replace authorization or rate limiting.

Clients send extensions.persistedQuery carrying a sha256Hash digest; servers look up hash → GraphQL query text and execute as if the full document shipped.

Quick wiring with grx.NewServer

package main

import (
	"log"

	"example.com/hello-grx/graph"

	"github.com/grx-gql/grx"
)

func main() {
	queries := map[string]string{
		// Example: SHA-256(lowercase hex) of UTF-8 `query { ping }` via `printf '%s' 'query { ping }' | shasum -a 256`.
		"d7b0dfafc61a1f0618f4f346911d5aa87bef97b134f2943383223bdac4410134": `query { ping }`,
	}

	srv, err := grx.NewServer(
		grx.WithSchema(graph.Schema()),
		grx.WithPersistedQueries(queries),
	)
	if err != nil {
		log.Fatal(err)
	}
	_ = srv
}

The default HTTP transport matches known digests (case-insensitive hex) and substitutes core.Request text before Execute runs.

Stronger closures - reject anything not APQ‑shaped, verify hash matches inlined body, or full trusted corpus mapping - sit on [server.Config](https://pkg.go.dev/github.com/grx-gql/grx/server#Config) (RequirePersistedQuery, StrictPersistedQueries, TrustedDocuments). Those fields map into the same http decoding path - see Limits → Persisted & trusted corpus.

Companion reading

Treat APQ alongside timeouts, MaxHTTPRequestBytes, and WithDisableIntrospection whenever you tighten a public POST graph endpoint - pair Limits, Introspection, and Security.

See also

  • Limits - persisted & trusted corpus
  • Automatic persisted query negotiation is not part of the current persisted query guide. Use persisted and trusted documents when the server can define the allowed query corpus.
Edit this page on GitHub

Last updated on

On this page