API Patterns and Practices: GraphQL
Designing GraphQL APIs well, with runnable examples in Quarkus SmallRye GraphQL and Python Strawberry against one canonical SDL contract.
What this site is
A chapter-based, hands-on path to designing GraphQL APIs well, built around a
single GraphQL schema in SDL β diffed
for breaking changes by
graphql-inspector β for a
shipping and cargo domain. GraphQL here is the read-oriented tracking view: one
query-shaped graph that stitches cargo, route legs, and handling events together,
so a client asks for exactly the fields it needs in a single round trip. Every
hands-on chapter ships the same example in both Quarkus
(SmallRye GraphQL) and Python (Strawberry). Both are code-first: CI diffs each
service's exported schema against the canonical SDL and asserts every response
against it, so a 200 that carries a result that does not match the schema fails
the build. You work through schema design,
queries and mutations, resolvers and the N+1 problem with dataloaders,
pagination, error handling, schema evolution, query cost limits, persisted
queries and caching, security, observability, federation, subscriptions,
testing and debugging, and running the service on Kubernetes. It assumes you can
read Java and Python; it is not a tutorial in either language. The code tabs
are built to admit more stacks later. All container images are UBI-based, and
the stack runs on Docker Compose and minikube.
Prerequisites & the Lab
Get the code-first GraphQL toolchain running locally: Quarkus SmallRye GraphQL, Python Strawberry, Docker Compose + LGTM, and the shipping/cargo tracking domain.
Why GraphQL & the Decision Lens
Decide whether GraphQL fits an interaction and place it against REST and RPC for read-heavy, graph-shaped data.
The Schema: SDL & the Type System
Model the tracking view in SDL and make one canonical schema the contract both stacks export and are checked against.
Execution: Resolvers, Queries & Mutations
Explain how a query is parsed, validated and executed, and implement queries, resolvers and mutations in both stacks.
Reliability: Errors & Partial Results
Return partial data with typed errors so one failing field never takes down the whole response.
Schema Evolution & the Living Contract
Design and evolve a schema without breaking clients, enforced by a breaking-change gate in CI.
Data Fetching at Scale
Paginate large lists with connections and eliminate N+1 fetches with batching and dataloaders.
Performance & Safety
Bound what a client can ask for with depth limits, cost analysis, persisted queries and caching.
Security
Secure the transport, control introspection, and authenticate and authorize at the field level.
Observability & the Gateway
Trace and measure resolvers, and compose several subgraphs behind one federated gateway.
Real-time & Client Integration
Push live tracking updates with subscriptions and consume the graph from typed clients.
Testing & Debugging
Prove conformance, load-test the graph, and diagnose a misbehaving GraphQL service end to end.
Running It & the Final Project
Run, observe, and defend a complete GraphQL tracking system across Compose, minikube and OpenShift Local.