Best Practices
Schema design choices made in week one outlive most of the code around them. These are the rules that hold up after years in production.
GraphQL - production rules
EXAMPLE
# 1. Nullable by default, non-null when you mean it
# A non-null field that ever errors poisons the whole parent object.
type User {
id: ID!
email: String! # truly required
displayName: String # may be unset, do not force a fallback
team: Team # may be null if user is unattached
}
# 2. Pagination uses connections (cursor), never offset
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
}
type UserEdge { node: User!; cursor: String! }
type PageInfo {
hasNextPage: Boolean!
hasPreviousPage: Boolean!
startCursor: String
endCursor: String
}
# 3. Mutations return a payload type, not a bare result
type CreateUserPayload {
user: User
errors: [UserError!]!
}
type UserError { field: String; code: String!; message: String! }
# 4. Errors: surface domain errors in the payload, reserve top-level
# errors for true execution failures.
# 5. Avoid deeply nested writes. One mutation, one logical action.
# 6. Use @deprecated, never breaking changes.
type Order {
total: Float! @deprecated(reason: 'Use totalCents to avoid float drift')
totalCents: Int!
}
# 7. Persist queries in production (Apollo PQL, Relay automatic).
# Reject unknown operations - blocks both arbitrary queries and probing.
# 8. Authorization in resolvers, not at the schema edge.
# Field-level checks let you return null for unauthorised fields
# instead of failing the whole request.
# 9. Caching: stable IDs (Relay global IDs or type:id) so clients can dedupe.
# 10. Observability: trace per resolver, sample by operation name.
# Slow resolvers hide inside fast endpoints.
Why it matters
GraphQL gives clients power; schema design is how you keep that power bounded. Pagination by cursor, payloads with explicit errors, persisted queries in production, and stable IDs for caching are the foundations - everything else negotiates from there.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Nullable by default. Errors as union types. Pagination from day one. Document with descriptions.Try it Yourself »
Discussion
Loading…