Mutations Perform Writes
A mutation is a GraphQL operation, written with the mutation keyword, whose top-level fields represent operations that change data on the server — creating, updating, or deleting records — rather than merely reading it. Mutations use the exact same selection-set syntax as queries; the distinction is purely about intent and, critically, about execution order, since the GraphQL spec explicitly separates the two operation types so tooling and servers can treat writes differently from reads.
Cricket analogy: A mutation like recordDelivery(input: {...}) is like a scorer physically updating the official scorecard after a ball is bowled, as opposed to a query which is like a fan just refreshing the app to view the current score without changing anything.
Structuring a Mutation: Input and Payload
The dominant convention, though not a hard spec requirement, is for each mutation to accept a single argument named input, typed as a dedicated input object (e.g. CreatePostInput), and to return a corresponding payload object type that bundles the changed record together with any errors, for example CreatePostPayload { post: Post, errors: [UserError!] }. This convention keeps mutation signatures stable as new fields are added to the input or payload over time, since adding a field to an object type is non-breaking, whereas adding a new required positional argument would break every existing caller.
Cricket analogy: Wrapping arguments in a RecordDeliveryInput type is like a scoring app using one structured 'ball event' form with named fields instead of a bowler shouting five separate loose values down a radio, so adding a new field like 'no-ball reason' later doesn't break the existing recording pipeline.
Mutations Execute Serially, Queries in Parallel
The GraphQL specification guarantees that top-level fields within a single mutation operation are executed serially, one completing before the next begins, whereas top-level fields within a query operation may be executed in parallel. This matters because if a client sends two mutations in one request — say, deductInventory followed by createOrder — the server guarantees the first finishes (with whatever side effects) before the second starts, preventing race conditions between dependent writes issued in the same document.
Cricket analogy: This is like an umpire ensuring a no-ball call is fully processed and the free-hit flag set before the next delivery's outcome is recorded, rather than both being resolved simultaneously and risking an inconsistent scorecard.
mutation AddComment($input: AddCommentInput!) {
addComment(input: $input) {
comment {
id
body
createdAt
author {
name
}
}
errors {
field
message
}
}
}
# variables:
# { "input": { "postId": "p_42", "body": "Great write-up!" } }Because a mutation's response uses the same selection-set syntax as a query, you can request back exactly the fields your UI needs to update immediately — for example the newly created comment's id and createdAt — letting client libraries like Apollo Client or Relay merge the result straight into their normalized cache without a separate refetch.
Mutation Naming and Idempotency Are Conventions, Not Guarantees
GraphQL itself enforces no particular naming scheme or idempotency guarantee for mutations — those are conventions the schema author chooses to follow, commonly a verbNoun pattern like createPost, updatePost, or deletePost. Because mutations are arbitrary server-defined operations, nothing in the spec prevents a poorly designed mutation from being non-idempotent in a way that surprises callers, so schema authors typically document explicitly whether calling a mutation twice with the same input is safe to retry.
Cricket analogy: Naming a mutation recordDelivery instead of just ball is like a scoring team agreeing on a house style — verbNoun for anything that changes the ledger — but the GraphQL engine itself doesn't enforce that convention any more than the laws of cricket dictate scorer terminology.
If a single request contains multiple mutation fields, GraphQL guarantees only their execution order, not transactional rollback — if the second mutation fails after the first already succeeded, the first mutation's side effects are not automatically undone. Any all-or-nothing guarantee has to be implemented explicitly in your own resolver or database transaction logic.
- Mutations, declared with the mutation keyword, represent write operations and use the same selection-set syntax as queries.
- The common convention is a single 'input' argument (a dedicated input type) and a 'payload' return type bundling the result and errors.
- Top-level fields in a single mutation operation execute serially; top-level query fields may execute in parallel.
- Requesting fields back in the mutation response lets clients update their cache without a separate refetch.
- Naming conventions like verbNoun (createPost) and idempotency guarantees are team choices, not enforced by the GraphQL spec.
- Multiple mutations in one request are ordered but not automatically transactional — partial failure does not auto-rollback earlier mutations.
Practice what you learned
1. What execution order guarantee does the GraphQL spec make for top-level fields within a single mutation operation?
2. Why is the input/payload pattern (a single 'input' argument and a 'payload' return type) commonly used for mutations?
3. If a client sends two mutations in one request and the second one fails after the first succeeded, what happens by default?
4. Does the GraphQL specification enforce mutation naming conventions like verbNoun (e.g. createPost)?
Was this page helpful?
You May Also Like
Input Types
Learn how GraphQL input object types bundle structured arguments together, especially for mutations, and how they differ from regular object types.
Writing Queries
Learn how to construct GraphQL queries that ask a single endpoint for exactly the fields you need, nested through the schema graph.
Aliases and Fragments
Learn how aliases let you request the same field multiple times with different arguments, and how fragments keep repeated selection sets DRY.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics