Write component-specific GraphQL queries
Context
A common anti-pattern is treating GraphQL queries like REST endpoints — creating "reusable" queries that fetch all possible fields to serve multiple components. This negates GraphQL's core benefit. Think of it like SQL: you wouldn't write one giant SELECT * query and reuse it everywhere.
Decision
Each view or component declares its own data requirements through a dedicated query.
1. Write component-specific queries
# ProfileView.graphql
query ProfileView {
me { userId, username, email }
}
# UserMenuBadge.graphql
query UserMenuBadge {
me { username } # Only what the badge needs
}
Not a shared "god query" that fetches everything any component might need. The schema is shared; the queries are not.
2. Use fragments for type consistency, not reuse
Fragments have two legitimate uses: ensuring consistent return types across mutations that return the same type, and mapping to reusable UI components.
# TripFields.graphql — consistent Trip data across mutations
fragment TripFields on Trip {
id
purpose
destinations { location { rawName }, durationDays }
}
mutation UpdateDestinationLocation(...) {
updateDestinationLocation(...) { ...TripFields }
}
mutation AddUserIntent(...) {
addUserIntentModification(...) { ...TripFields }
}
Don't create fragments that over-fetch to serve unrelated components.
3. Query duplication is not code duplication
Having similar-looking queries in different files is correct GraphQL usage. ProfileView and LoginView might both query me { userId, username, email } — that's precision, not duplication. Future changes to one won't affect the other.
Consequences
Each request contains exactly the required data. Component data requirements are colocated with component code. Components evolve independently.
The cost is more query files and perceived duplication that developers familiar with REST may initially resist.