Photo by Yosuke Ota on Unsplash

On this page

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

  1. 1. Which types may GraphQL operation variables use?

Search articles

Type a word to search published articles.

Open the search page