100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
GraphQL

Mutations Explained

Learn how GraphQL mutations perform writes, why they execute serially, and how to structure inputs and response payloads.

Queries & MutationsIntermediate10 min readJul 10, 2026
Analogies

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.

graphql
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

Was this page helpful?

Topics covered

#GraphQL#GraphQLStudyNotes#WebDevelopment#MutationsExplained#Mutations#Explained#Perform#Writes#APIs#StudyNotes#SkillVeris