Schema Design First Principles
A GraphQL schema is an API contract, so schema design should begin with the needs of API consumers and the domain rather than the shape of database tables.
A database model might contain:
users
user_profiles
user_addresses
user_login_metadata
That does not mean the GraphQL schema should expose those tables directly.
Instead, the API should model meaningful domain concepts:
type User {
id: ID!
name: String!
profile: Profile
addresses: [Address!]!
}
The GraphQL layer is an abstraction boundary.
Design around capabilities
Prefer operations that represent meaningful business actions:
cancelOrder(id: ID!): CancelOrderPayload!
rather than exposing implementation-oriented operations:
setOrderStatus(id: ID!, status: String!): Order!
The first expresses a business capability. The second exposes an internal state mutation that may allow invalid transitions.
Make invalid states difficult to represent
Use enums instead of arbitrary strings where values are constrained.
Use non-null types where a value is genuinely guaranteed.
Use input types for structured client data.
Use dedicated payload types when an operation has meaningful result metadata.
A well-designed schema communicates domain rules before a client ever reads the resolver implementation.
Model business concepts rather than database tablesUse meaningful types and enumsExpose valid business actions- Do not automatically expose database models as GraphQL schema types.
- Design around domain concepts and client capabilities.
- Use the type system to communicate meaningful constraints.
- A GraphQL schema should remain stable even when implementation details change.
Why should a GraphQL schema generally not mirror database tables directly?