This chapter follows Input types and arguments.
A GraphQL document can contain multiple operations, each with a type (query, mutation, or subscription) and optional name. Named operations improve logs, persisted-query registries, and Apollo Studio traces. Anonymous documents are allowed when exactly one operation is present.
Queries and selection sets
A query read operation uses a selection set { ... } to list fields:
query UserProfile($id: ID!) { user(id: $id) { name posts(first: 5) { title } }}Variables ($id) are typed and passed in a separate JSON object alongside the document. All variables must be scalars, enums, or input objects.
Mutations
Mutations change server-side state. Top-level mutation fields execute in order, unlike query fields:
mutation ArchivePost($id: ID!) { archivePost(id: $id) { id archivedAt }}Return fields from the mutation payload so clients update UI without a follow-up query—a common schema design guideline covered in the servers chapter.
Subscriptions
Subscriptions maintain a channel (typically WebSocket with the graphql-transport-ws protocol) for server-pushed updates:
subscription OnCommentAdded($postId: ID!) { commentAdded(postId: $postId) { id body }}Clients must handle reconnect, auth on connection_init, and backpressure; subscriptions share authorization concerns with queries but add long-lived connection state.
Variables and operation names
Production documents should name operations and declare variables explicitly:
query OrderList($status: OrderStatus) { orders(status: $status) { id total }}{ "status": "PENDING" }Hard-coded literals in queries make codegen and persisted-query hashes harder to reuse across environments.
Aliases and fragments
Aliases rename fields in the response:
query Compare { draft: post(id: "1") { title } published: post(id: "2") { title }}Fragments reuse field sets on a type:
fragment PostSummary on Post { id title}
query Feed { posts { ...PostSummary }}Fragment names must match the type in on Post. Variables used inside fragments inherit from the enclosing operation.
Inline fragments and directives
For interfaces and unions, inline fragments select type-specific fields:
search(text: "graph") { __typename ... on Book { title } ... on Author { name }}Directives @include(if: $flag) and @skip(if: $flag) conditionally include fields based on variables—handy for feature flags without duplicating entire operations.
Sending operations over HTTP
Most clients POST JSON { "query", "variables", "operationName" }. Some gateways allow GET with a query parameter for cache-friendly reads; mutations should stay on POST. The servers and security chapters discuss CSRF implications of GET.
Next: Resolvers and execution.
Check your understanding
Question 1 of 7
0 of 7 checked